JavaScript 常见算法面试(一)

目录

1.超过范围的两个大整数相加

2.实现数组扁平化

3.数组去重

4.求数组中的最大值/最小值

5.最大公约数、最小公倍数

6.反串单向链表

7.实现 indexOf() 方法

8.判断回文字符串

9.累加函数 reduce()

10.reduce() 实现 forEach、map、filter

11.设计任务队列,分别在 1、3、4 秒后打印出 “1”, “2”, “3”

12.查找出现频率最高的字符

13.爬楼梯(动态规划)


1.超过范围的两个大整数相加

  • 主要思路:将数字转换为字符串,每个字符串按位相加
function bigNumberAdd(number1, number2) {
    let result = "", 
        carry = false; 
    number1 = number1.split("");
    number2 = number2.split("");
    while (number1.length || number2.length || carry) {
        carry += ~~number1.pop() + ~~number2.pop();
        result = carry % 10 + result;
        carry = carry > 9;
    }
    return result;
}
var sum = bigNumberAdd('1000', '500');
console.log(sum);

2.实现数组扁平化

  • 数组扁平化:将一个多维数组变为一维数组,两种方法:
  1. 递归:遍历最外层数组的每一个元素,如果是数组,继续递归执行;不是数组,放到最后的结果数组当中
  2. array.toString().split(",").map()
var arr = [1, [2, [3, 4]]]; // [1, 2, 3, 4]
// 1.递归
var result = [];
function flattern1(array) {
    for (var i = 0; i < array.length; i++) {
        if (Array.isArray(array[i])) {
            flattern1(array[i])
        } else {
            result.push(array[i])
        }}
    return result; // 
}
console.log(flattern1(arr));

// 2.array.toString().split(",").map()
function flattern2(array) {
    return array.toString().split(",").map(function(item) {
        return +item; 
    })
}
console.log(flattern2(arr)); 

3.数组去重

  1. indexOf()
  2. new Set()
function unique1(array) {
    if (!Array.isArray(array) || array.length <= 1) return;
    var result = [];
    array.forEach(function(item) {
        if (result.indexOf(item) === -1) {
            result.push(item);
        }
    })
    return result;
}

function unique2(array) {
    if (!Array.isArray(array) || array.length <= 1) return;
    return new Set(array);
}

4.求数组中的最大值/最小值

  • Math.max.apply(null,array)
  • Math.min.apply(null,array)
var arr = [6, 4, 1, 8, 2, 11, 23];
// 方法一:
console.log(Math.max.apply(null, arr)) // 23
console.log(Math.min.apply(null, arr)) // 1
// 方法二:
function getMax(array) {
    max = array[0]
    for (var i = 0; i < array.length; i++) {
        max = Math.max(array[0], array[i])
    }
    return max;
}

5.最大公约数、最小公倍数

  • 求最大公约数基本思想:辗转相除,用大数除以小数,再用小数除以余数,一直递归,直到余数为0
  • 求最小公倍数基本思想:两数相乘,除以它们的最大公约数
function getMaxCommonDivisor(a, b) { // 求最大公约数
    if (b === 0)
        return a;
    return getMaxCommonDivisor(b, a % b);
}
function getMinCommonMultiple(a, b) { // 求最小公倍数
    return a * b / getMaxCommonDivisor(a, b);
}
var result = getMinCommonMultiple(6, 8)
console.log(result);

6.反串单向链表

  • 使用三个变量分别表示:当前节点、前节点、后节点
  • 从头节点往后遍历,先获取下一个节点,然后将后节点设置为前节点,循环
var reverseList = function(head) {
    if (!head || !head.next) return head;
    let pre = null; 
    let current = head;
    let next;
    while (current) { 
        next = current.next;
        current.next = pre; 
        pre = current; 
        current = next; 
    }
    return pre;
};

7.实现 indexOf() 方法

function indexFun(array, val) {
    if (!Array.isArray(array))
        return;
    for (var i = 0; i < array.length; i++) {
        if (array[i] === val) {
            return i; 
        }}
    return -1; 
}

8.判断回文字符串

  • 原理:判断翻转后的字符串和原来的字符串是否相同
function isPalindrome(str) {
    let reg = /[\W_]/g,
        newStr = str.replace(reg, "").toLowerCase(),
        reverseStr = newStr.split("").reverse().join("");
    return reverseStr === newStr;
}

9.累加函数 reduce()

  • 剩余参数:...args 以...为前缀,是个数组
  • reduce() 方法:接收一个函数作为累加器,数组中的每个元素都要执行该函数
  • arr.reduce(function(上次函数返回值,当前要处理的值){},第一次调用时作为上次函数返回值的值)​​​​​​​
function sum(...args) {
    var result;
    result = args.reduce((pre, item) => pre + item);
    return result;
}
// 剩余参数包含:没有对应形参的实参
// arguments包含:传给函数的所有实参

10.reduce() 实现 forEach、map、filter

// 使用 reduce 方法实现 forEach、map、filter
// forEach 遍历,处理
function forEachUseReduce(array, handler) {
    array.reduce(function(pre, item, index) {
        handler(item, index); 
    });}
// map 遍历,处理,返回结果
function mapUseReduce(array, handler) {
    let result = [];
    array.reduce(function(pre, item, index) {
        let mapItem = handler(item, index);
        result.push(mapItem);
    });
    return result;
}
// filter 遍历,满足条件的处理,返回结果
function filterUseReduce(array, handler) {
    let result = [];
    array.reduce(function(pre, item, index) {
        if (handler(item, index)) { 
            result.push(item);
        }});
    return result;
}

11.设计任务队列,分别在 1、3、4 秒后打印出 “1”, “2”, “3”

async function one() {
    setTimeout(function() {
        console.log(1);
    }, 1000);}
async function two() {
    setTimeout(function() {
        console.log(2);
    }, 3000);}
async function three() {
    setTimeout(function() {
        console.log(3);
    }, 4000);}
async function run() {
    var p1 = await one();
    var p2 = await two();
    var p3 = await three();
}
run(); 

12.查找出现频率最高的字符

  • 遍历字符串,把字符串作为对象属性
  • 判断对象是否存在该属性,若存在则属性值累加,若不存在则属性值设为1
  • 遍历对象,寻找最大的属性值(字符出现次数),属性名(出现字符)
function getStrMax(str) {
    let obj = {};
    for (let i = 0; i < str.length; i++) {
        if (obj[str.charAt(i)]) {
            obj[str.charAt(i)]++;
        } else {
            obj[str.charAt(i)] = 1;
        }}
    let max = 0;
    let maxstr;
    for (let key in obj) {
        if (max < obj[key]) {
            max = obj[key]
            maxstr = key
        }}
    console.log(maxstr + '出现了' + max + '次');
}

13.爬楼梯(动态规划)

  • 由分析可知,假设只差最后一步就能走上第10级阶梯,这个时候一共有两种情况​​​​​​​
  • 因为每一步只允许走1级或2级阶梯, 因此分别为从8级阶梯和从9九级阶梯走上去的情况​​​​​​​
  • 从0到10级阶梯的走法数量 = 从0到9级阶梯的走法数量 + 从0到8级阶梯的走法数量​​​​​​​
  • 依次类推,可以得到递归关系,结束的标志:从0到1级阶梯的走法数量 + 从0到2级阶梯的走法数量​​​​​​​
function getClimbingWays1(n) {
    if (n < 1) {
        return 0;
    }
    if (n === 1) { 
        return 1;
    }
    if (n === 2) { 
        return 2; 
    }
    return getClimbingWays1(n - 1) + getClimbingWays1(n - 2);
}

let map = new Map(); 
function getClimbingWays2(n) {
    if (n < 1) {
        return 0;
    }
    if (n === 1) {
        return 1;
    }
    if (n === 2) {
        return 2;
    }
    if (map.has(n)) { 
        return map.get(n); 
    } else {
        let value = getClimbingWays2(n - 1) + getClimbingWays2(n - 2);
        map.set(n, value); 
        return value; 
    }}

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Lyrelion

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值