2020 祝安,缝隙中寻找机遇:面试题第三波:算法

204 阅读3分钟

非常感谢,前同事行长@onlyadaydreamer分享的面经。

北京新发地的海鲜市场怎么回事啊。 端午的票也赶紧退了。不敢回家了。

直接正文!时间紧迫!

合并两个有序表

输入: [1, 2, 3] [1,3,4,5]
输出:[1,2,3,4,5];
要求时间复杂度为o(n)
//最简单的方法。
var a = [1,2,3]

var b = [1,3,4,5]

var c = [...new Set([...a,...b])]

c
(5)[1, 2, 3, 4, 5]
//代码太多了。
function fn (arr1, arr2) {
    let i = 0, j = 0, k = 0;
    let arr = [];

    while(i < arr1.length && j < arr2.length) {
        if (arr1[i] < arr2[j]) {
            arr[k++] = arr1[i++];
        } else {
            arr[k++] = arr2[j++];
        }
    }
    if (i < arr1.length) {
        // arr.concat(arr1.slice(i));// 注意不能用concat,concat返回的是一个新的数组,arr没有变化
        arr.push(...arr1.slice(i));
    } else {
        arr.push(...arr2.slice(j));
    }
    return arr;
}
console.log(fn([1,2,3], [1,3,4,5]));

给一个整数n,不用循环生成一个数组[1, ...n]

function fn (n, arr) {
    if (n === 0) return arr;

    return fn(n-1, arr.concat(n));
}
// console.log(fn(10, []));

function curring (fn, arr) {
    return function(m) {
        return fn.call(this, m , arr);
    }
}

let f = curring(fn, []);
console.log(f(10));

求一个字符串中最长的无重复子串的长度

var lengthOfLongestSubstring = function(s) {
    var res = 0; // 用于存放当前最长无重复子串的长度
    var str = ""; // 用于存放无重复子串
    var len = s.length;
    for(var i = 0; i < len; i++) {
      var char = s.charAt(i);
      var index = str.indexOf(char);
      if(index === -1) {
        str += char;
        res = res < str.length ? str.length : res;
      } else {
        console.log(char, index, str);
        str = str.substr(index + 1) + char;// 如果重复了那就把这个重复的字符放在最末尾
      }
    }
    return res; 
};

给定字符串a1_b2_c3_d4_e5,不用循环输出a1c3e5

let str = `a1_b2_c3_d4_e5`.replace(/[a-z][1-9]/g, function(res) {
    let arr = res.split('');
    
    if (arr[1]%2 !== 0) {
        return res;
    } else {
        return '';
    }
});
console.log(str.replace(/\_/g, ''));

通过命名空间访问对象的属性

比如给定{a:{b:{c:1}}}, 取a.b.c

function fn(obj, str) {
    if (obj == null || typeof obj !== 'object' || JSON.stringify(obj) === '{}') return;

    let path = str.split('.');
    return path.reduce((pre, next) => {
        return pre[next];
    }, obj);
}

console.log(fn({a:{b:{c:1}}}, 'a.b.c'));

计算两个数组的交集

function fn (arr1, arr2) {
    let res = [];
    for (let i = 0; i < arr1.length; i++) {
        if (arr2.includes(arr1[i])) {
            res.push(arr1[i]);
        }
    }
    return res.filter((item, index) => { return index === res.indexOf(item)});
}

求两个数的最大公约数

function fn(a, b) {
    let res = [];
    for (let i = 1; i < a && i < b;i++) {
        if (a % i == 0 && b % i == 0) {
            res.push(i);
        }
    }
    return res;
}
Math.max.apply(null, fn(12, 24));
Math.max(...fn(12, 24));
console.log(fn(12, 24));

x个元素的数组,按Y个一组拆成二维数组,用reduce实现

// [1, 2, 3, 4, 5] => [[1,2], [3,4], 5]
function fn(arr, y) {
    let res = [];
    return arr.reduce((pre, next) => {
       let last = pre[pre.length - 1];
       if (last && last.length < y) {
           last.push(next);
       } else {
            let arr2 = [];
            arr2.push(next);
            pre.push(arr2);
       }
       return pre;
    }, res);
}
console.log(fn([1, 2, 3, 4, 5], 2));

检测碰撞

function testColl(x1, y1, w1, h1,
    x2, y2, w2, h2) {
    var l1 = x1;
    var r1 = x1 + w1;
    var t1 = y1;
    var b1 = y1 + h1;

    var l2 = x2;
    var r2 = x2 + w2;
    var t2 = y2;
    var b2 = y2 + h2;
    if (r1 < l2 || l1 > r2 || b1 < t2 || t1 > b2) {
        return false;
    } else {
        return true;
    }
}

查询数组中出现次数最多的元素

思路:

使用一个对象来计数, 对象的键就是数组元素, 是唯一的

遍历对象找到最大的那一个


let arr = [1,3,3,4,5,6,4,3]
function func(arr) {
    let json = {}
    for (let i = 0; i < arr.length; i++) {
        if (json[arr[i]]) {
            json[arr[i]] ++
        } else {
            json[arr[i]] = 1
        }
    }

    let maxValue = null
    let maxKey = null
    for (let key in json) {
        if (maxValue < json[key]) {
            maxValue = json[key]
            maxKey = key
        }
    }
    return `出现次数最多的元素是${maxValue}, 次数为${maxKey}`
}

写一个斐波那契数列求值算法,给定一个下标n求出对应的值.

斐波那契数列:1,1,2,3,5...

输入1,输出1

输入2,输出1

输入3,输出2

function fn (n) {
    if(n === 1 || n === 2) return 1;

    return fn(n-1) + fn(n-2);
} 

console.log(fn(1));
console.log(fn(2));
console.log(fn(3));
console.log(fn(40));

如何优化?

let cache = {};

function fn (n) {
    if (cache[n]) return cache[n];
    if(n === 1 || n === 2) return 1;
    let res = fn(n-1) + fn(n-2);
    cache[n] = res;
    return res;
} 

实现一个sum函数,其调用方式及返回结果如下例:

sum(1,2)(3).valueOf();// 6

sum(4)(3,2,1)(5,6).valueOf();// 21

function sum (...args1) {
   let fn = function(...args2) {
        return sum.apply(null, [...args1, ...args2]);
   }
   fn.valueOf = function () {
        return args1.reduce((pre, next) => {
            return pre + next;
        });
   }

   return fn;
}

let res = sum(1, 2)(1, 2)(3)(5).valueOf();
console.log(res);

回文字符串的判断 abccba

function f (str) {
    let s = '';
    for (let i = str.length - 1; i >= 0; i--) {
        s += str[i];
    }
    return s === str;
}