2020秋招笔试/面试编程题小记

2020秋招笔试/面试编程题小记

自己对秋招过程中的一些算法题、编程题的一些复盘(非网络搜集)

一、图的遍历

1. 求带权图的最大路径

问题描述

图(A、B、C、D、E、F、G)

A B 100
B D 100
D E 50
A C 200
C G 300
A F 100

A->B->D->E 250

A->C->G 500

A->F 100

B->D->E 150

C->G 300

找到权重最大的路径,输出出来(如果有多条一样的,全部都输出)

解题方案

// 路径遍历
let read_line = (function (){
    let i = 0
    data = [
        'A B 100',
        'B D 100',
        'D E 50',
        'A C 200',
        'C G 300',
        'A F 500',
    ]
    return function (){
        return data[i++]
    }
})()

function main(){
    // 定义路径树,最终将会生成如下:
    /*
     { A: { B: 100, C: 200, F: 100 },
       B: { D: 100 },
       D: { E: 50 },
      C: { G: 300 } }*/

    let TREE = {}

    let MaxValue = 0 , MaxRoads = []

    let read  = read_line()

    while(read){
        let p = read.split(' ')
        let begin = p[0],end = p[1],value = parseInt(p[2])
        // 生成路径树
        TREE[begin] = {...TREE[begin],[end]:value}
        read = read_line()
    }
    /**
     * 回溯函数
     * @param {String} begin 起点键值
     * @param {Object} tree 路径树
     * @param {Number} value 当前路径权值 
     * @param {String} road 已走过的路径
     */
    function resolve(begin,tree,value,road){
        if(!tree[begin])return

        for (const end in tree[begin]) {
            if (tree[begin].hasOwnProperty(end)) {
                const element = tree[begin][end];

                let currentValue = value+element,currentRoad = road+'->'+end

                if(!TREE[end] && currentValue > MaxValue){
                    // 抵达终点,当前值比之前的最大值还要大,更新MaxValue和路径数组
                    MaxValue = currentValue
                    MaxRoads = [currentRoad]
                    continue
                }else if(!TREE[end] && currentValue == MaxValue){
                    // 抵达终点,当前值等于之前的最大值,路径数组新增路径
                    MaxRoads.push(currentRoad)
                }else if(TREE[end]){
                    // 还没有抵达终点,继续向下走
                    resolve(end,tree,currentValue,currentRoad)
                }
            }
        }
    }
    for (const begin in TREE) {
        if (TREE.hasOwnProperty(begin)) {
            // 遍历路径树下的各个起点,开始路径计算
            resolve(begin,TREE,0,begin)
        }
    }
    MaxRoads.map(road=>console.log(road,MaxValue))
}

main()

2. 小D去旅游

问题描述

小D要在某个时间点要从A点到B点,A到B有可能有多种不同的路径方案,计算小D走花费时间最小路径到达B点后的时间。

输入第一行 N:节点个数,M:边的个数

输入之后的M行都是 节点begin 节点end 需要花费的时间(小时)

最后一行再输入 小D要出发的点 到达的点 起始时间(起始时间格式:month.day/hour)

输出 小D抵达的时间month.day/hour

样例1:

输入:
4 4
1 2 5
1 3 6
2 4 8
3 4 6
1 4 7.9/8

输出:
7.9/20 
注:1->3->4 = 12小时

样例2:

输入:
4 4
1 2 25
1 3 18
2 4 28
3 4 22
1 4 7.9/8

输出:
7.11/0
注:1->3->4 = 40小时

解决方案

let read_line = (function (){
    let i = 0
    let data = [
        '4 4',
        '1 2 25',
        '1 3 18',
        '2 4 28',
        '3 4 22',
        '1 4 7.9/8',
        ]
    // let data = [
    //     '4 4',
    //     '1 2 5',
    //     '1 3 6',
    //     '2 4 8',
    //     '3 4 6',
    //     '1 4 7.9/8',
    //     ]
    return function (){
        return data[i++]
    }
})()

function main(){
    let args = read_line().split(' ')
    let N = args[0]
    let M = args[1]

    // 默认为最大time
    let result = 1000000000000000
    let TREE = {}
    for(let i=0;i<M;i++){
        let p = read_line().split(' ').map(e=>parseInt(e))
        let begin = p[0],end = p[1],time = p[2]
        if(TREE[begin])TREE[begin][end] = time
        else{
            TREE[begin] = {
                [end]:time
            }
        }
    }

    // 获取起点、终点和时间
    let p = read_line().split(' ')
    let Begin = p[0],End = p[1],BeginTime = p[2]
    // 构建回溯函数
    function resolve(begin,end,tree,price){
        if(!tree[begin])return 
        for (const key in tree[begin]) {
            if (tree[begin].hasOwnProperty(key)) {
                const element = tree[begin][key];
                // 找到终点
                if(key == end && price+element<result){
                    result = price+element
                    continue
                }
                if(key != end && price+element < result){
                    resolve(key,end,tree,price+element)
                }
            }
        }
    }
    // 获取最小需要花费的时间 => result
    resolve(Begin,End,TREE,0)

    // 返回值为加了result时间后的时间字符串
    function addHour(time,hours){
        let [month,day,hour] = time.split(/[\.\/]/)
        let resHour = parseInt(hour)+parseInt(hours)
        let a = new Date(2020,month-1,parseInt(day)+parseInt(resHour/24),resHour%24)
        return `${a.getMonth()+1}.${a.getDate()}/${a.getHours()}`

    }
    console.log(addHour(BeginTime,result))

}
main()

3. 省钱造桥术

问题描述

城市管理者要把若干岛屿造桥连接起来,并限定造每条桥的最大成本,设计程序查看是否能在这种情况下把所有岛屿连接起来。

第一行输入T 代表组数

第二行输入第一组的 N节点数 M边数 最大成本K

接下来的M行 : 小岛begin 小岛end 需要的花费

再输入第二组 ...

输出Yes或者No代表是否将所有岛屿连接起来

样例:

2
4 3 400
1 2 200
1 3 400
3 4 300
3 3 400
1 2 500
1 3 600
2 3 700

Yes
No

解决方案

let read_line = (function (){
    let i = 0
    let data = [
        '2',
        '4 3 400',
        '1 2 200',
        '1 3 400',
        '3 4 300',
        '3 3 400',
        '1 2 500',
        '1 3 600',
        '2 3 700',
        ]
    return function (){
        return data[i++]
    }
})()
main()
function main(args){
    let T = read_line()
    for(let i=0;i<T;i++){
        console.log(resolve())
    }
}

function resolve(){
    let args = read_line().split(' ').map(e=>parseInt(e))
    let N = args[0] // 小岛数目
    let M = args[1] // 边数
    let maxPrice = args[2] //最大成本

    // 定义数据树 { '1': { '2': 500, '3': 600 }, '2': { '3': 700 } }
    let TREE = {}
    for (let index = 0; index < M; index++) {
        let p = read_line().split(' ').map(e=>parseInt(e))
        let begin = p[0],end = p[1],price = p[2]
        if(TREE[begin]) TREE[begin][end] = price
        else{
            TREE[begin] = {
                [end]:price
            }
        }
    }
    // 结果状态树,存放满足最大成本的小岛为key
    let result = {}
    // 存放当前的已构建的桥数
    let sideCount = 0
    // 根据数据树 遍历小岛起点
    for (const begin in TREE) {
        if (TREE.hasOwnProperty(begin)) {
            const ends = TREE[begin]
            // 遍历小岛终点
            for (const end in ends) {
                if (ends.hasOwnProperty(end)) {
                    const element = ends[end]

                    if(element <= maxPrice){ //小于等于最大成本
                        // 将两个小岛都存放到结果树中
                        result[begin] = result[end] = true
                        // 增加桥数
                        sideCount++
                        // 如果当前结果树中,节点个数正好与N要求一致,并且边数正好是节点个数减一(防止1->2,3->4出现的错误) 则返回"Yes"
                        if(Object.keys(result).length === N && sideCount == N-1) return "Yes"
                    }
                }
            }
        }
    }
    return "No"
}

二、其他

1. 字符串全排列

题目描述

*全排列 'abc' -> ['abc', 'acb', 'bac', 'bca', 'cab', 'cba']

解题方案

function permutation(str) {
    let ans = []
    function Search(str = '',result = ''){
        if(str.length === 0)return ans.push(result)
        let arr = str.split('')
        for(let i = 0;i < arr.length;i++){
            let t = arr[i]
            arr[i] = ''
            Search(arr.join(''),result+t)
            arr[i] = t
        }
    }
    Search(str,"")
    return ans
}

2. 异步控制

题1

题目描述

function asyncAdd(a, b, callback) {

setTimeout(() => callbacl(null, a + b), 0);

}

asyncAdd(1, 2, function (err, result) {

if (err) throw err;

console.log(result); // 3

});

-- 题目

有一个数列:[1, 2, 3, ...., N]

基于 asyncAdd 完成数列的求和操作。

function sum(list) {

// TODO

}

sum([1, 2, 3, 4]).then(v => console.log(v)); // 10

解题方案

function asyncAdd(a, b, callback) {
    setTimeout(() => callback(null, a + b), 0);
}

function sum(list = []){
    return new Promise((resolve,reject)=>{
        if(list.length > 2){
            sum(list.slice(1)).then(data=>{
                asyncAdd(list[0],data,(err,data)=>{
                    resolve(data)
                })
            })
        }else{
            asyncAdd(list[0],list[1],(err,data)=>{
                resolve(data)
            })
        }
    })
}

sum([1,2,3,4]).then(console.log)

题2

题目描述

let tasks = [task1, task2, ..., taskN];

function seq(tasks) {

}

promise.then()

task1().then(() => task2()).then(() => task3())

模拟tasks

function asyncPrint(str){
    return function(){
        return new Promise((resolve,reject)=>{
            setTimeout(()=>{
                console.log(str)
                resolve()
            },Math.random()*1000)
        })
    }
} 

let tasks = [ asyncPrint("task1"), asyncPrint("task2"), asyncPrint("task3")]

解题步骤

解1:

function seq(tasks) {
    return tasks.reduce((pre,cur)=>{
        return pre.then(cur)
    },Promise.resolve())
}

解2:

function seq(tasks) {
    if(tasks.length == 0)return
    tasks[0]().then(()=>{
        seq(tasks.slice(1))
    })
}
#笔试题目#
全部评论

相关推荐

CrazyBucket:我今天下午也做梦在招聘会上面试一家小厂,给自己气笑了
点赞 评论 收藏
分享
1 1 评论
分享
牛客网
牛客企业服务