前端面试知识点整理——前端题库2(WXG)

前端面试知识点整理——前端题库2(WXG)

一、1013.将数组分成和相等的三个部分

在这里插入图片描述

/**
 * @param {number[]} arr
 * @return {boolean}
 */
var canThreePartsEqualSum = function(arr) {
    //分成三部分 每一个部分都是sum/3
    let sum = arr.reduce((a, b) => a + b);
    let num = 3;
    let temp = 0;
    for(let k of arr) {
        temp += k;
        if(temp === sum/3) {
            num--;
            temp = 0;
        }
    }
    return num <= 0;
};

二、704.二分查找

在这里插入图片描述

/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number}
 */
var search = function(nums, target) {
    let left = 0;
    let right = nums.length - 1;
    while(left <= right) {
        //这里floor和ceil都可以
        let middle = Math.floor(left + (right - left)/2); 
        if(nums[middle] == target) {
            return middle;
        } else if(nums[middle] > target) {
            right = middle - 1;
        } else {
            left = middle + 1;
        }
    }
    return -1;
};

三、100.相同树

在这里插入图片描述

/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} p
 * @param {TreeNode} q
 * @return {boolean}
 */
var isSameTree = function(p, q) {
    //深度优先搜索
    if(p == null && q == null) return true;
    if(p == null || q == null) return false;
    if(p.val != q.val) return false;
    return isSameTree(p.left, q.left) && isSameTree(p.right, q.right);
};

四、257.二叉树的所有路径

在这里插入图片描述

/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {string[]}
 */
var binaryTreePaths = function(root) {
    let res = [];
    let temp = '';
    function adding(root, temp) {
        if(root == null) return;
        if(root.left == null && root.right == null) { //叶结点
            temp = temp + root.val;
            res.push(temp);
            return;
        } else {
            temp = temp + root.val + '->';
        }
        adding(root.left, temp);
        adding(root.right, temp);

    }
    adding(root, temp);
    return res;
};

五、198.打家劫舍

在这里插入图片描述

/**
 * @param {number[]} nums
 * @return {number}
 */
var rob = function(nums) {
    //本来想用回溯来做的 算了写不出来
    
    let max = 0;
    if(nums.length == 0) return max;
    if(nums.length == 1) return nums[0];

    //动态规划 temp[i] = Math.max(temp[i - 1], temp[i - 2] + nums)
    let temp = [];
    temp[0] = nums[0];
    temp[1] = Math.max(temp[0], nums[1]);
    max = Math.max(temp[0], temp[1]);
    for(let i = 2; i < nums.length; i++) {
        temp[i] = Math.max(temp[i - 1], temp[i - 2] + nums[i]);
        max = Math.max(max, temp[i]);
    }
    return max;
};

六、106.从中序与后序遍历序列构造二叉树

在这里插入图片描述

/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {number[]} inorder
 * @param {number[]} postorder
 * @return {TreeNode}
 */
var buildTree = function(inorder, postorder) {
    //创建一个map存储所有的数组值和对应的下标 方便查找(对中序遍历数组的查找)
    const map = new Map();
    inorder.forEach((value, index) => {
        map.set(value, index);
    });
    //对于后序遍历数组,从后往前取值,作为每一个根节点
    let post;
    post = postorder.length - 1;

    //中序遍历数组的一棵子树的范围
    const helper = (left, right) => {
        if (left > right) {
            return null;
        }

        const value = postorder[post];
        const root = new TreeNode(value);

        // 根据 root 所在位置分成左右两棵子树
        const index = map.get(value); //获得在inorder中的位置

        post--;
        //这里要先建右子树 要注意postorder的从后往前的根状况
        root.right = helper(index + 1, right);
        root.left = helper(left, index - 1);
        return root;
    }
    return helper(0, inorder.length - 1);
};

七、2.两数相加

在这里插入图片描述
在这里插入图片描述

/**
 * Definition for singly-linked list.
 * function ListNode(val, next) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.next = (next===undefined ? null : next)
 * }
 */
/**
 * @param {ListNode} l1
 * @param {ListNode} l2
 * @return {ListNode}
 */
var addTwoNumbers = function(l1, l2) {
    let addition = 0;
    let head = null, tail = null;
    while(l1 || l2) {
        const n1 = l1? l1.val:0;
        const n2 = l2? l2.val:0;
        let sum = n1 + n2 + addition;
        if(!head) {
            head = tail = new ListNode(sum % 10);
        } else {
            tail.next = new ListNode(sum % 10);
            tail = tail.next;
        }
        addition = Math.floor(sum/10);
        if(l1) {
            l1 = l1.next;
        }
        if(l2) {
            l2 = l2.next;
        }
    }
    if(addition > 0) {
        tail.next = new ListNode(addition);
    }
    return head;
};

八、153.寻找旋转排序数组中的最小值

在这里插入图片描述

/**
 * @param {number[]} nums
 * @return {number}
 */
var findMin = function(nums) {
    //我的思路是用二分搜索
    let min = nums[0];
    function binary(left, right) {
        if(left > right) return; //定义递归结束条件
        let middle = Math.floor(left + (right - left)/2);
        if(nums[middle] >= min) { 
            binary(middle + 1, right);
        } else {
            min = nums[middle];
            binary(left, middle - 1);
        }
    }

    let left = 0, right = nums.length - 1;
    binary(left, right);
    return min;
};

九、189.旋转数组

在这里插入图片描述
使用多种方法:

/**
 * @param {number[]} nums
 * @param {number} k
 * @return {void} Do not return anything, modify nums in-place instead.
 */
var rotate = function(nums, k) {
    for(let i = 0; i < k; i++) {
        nums.unshift(nums.pop());
    }
    return nums;
};

十、4.寻找两个正序数组的中位数

在这里插入图片描述

自己做:(写得有点长)时间复杂度O(m + n)

/**
 * @param {number[]} nums1
 * @param {number[]} nums2
 * @return {number}
 */
var findMedianSortedArrays = function(nums1, nums2) {
    let m = nums1.length;
    let n = nums2.length;
    //记录中位数的位置
    let middle = Math.floor((m + n + 1) / 2); 
    let cnt = 0; //判断目前取出的数字个数
    let flag; //判断是两数相加/2 还是 直接中位数
    if((m + n) % 2 === 0) { 
        flag = 1;
    } else {
        flag = 0;
    }
    let res; //中位数
    while(nums1.length && nums2.length) {
        if(nums1[0] <= nums2[0]) {
            cnt++;
            var temp = nums1.shift();
        } else {
            cnt++;
            var temp = nums2.shift();
        }
        if(cnt == middle && flag) { //中位数要两者相加除二
            res = temp;
        }
        if(cnt == middle + 1 && flag) {
            res = (res + temp) / 2;
            break;
        }
        if(cnt == middle && !flag) { //直接中位数
            res = temp;
            break;
        }
    }
    while(nums1.length) {
        cnt++;
        var temp = nums1.shift();
        if(cnt == middle && flag) { //中位数要两者相加除二
            res = temp;
        }
        if(cnt == middle + 1 && flag) {
            res = (res + temp) / 2;
            break;
        }
        if(cnt == middle && !flag) { //直接中位数
            res = temp;
            break;
        }
    }
    while(nums2.length) {
        cnt++;
        var temp = nums2.shift();
        if(cnt == middle && flag) { //中位数要两者相加除二
            res = temp;
        }
        if(cnt == middle + 1 && flag) {
            res = (res + temp) / 2;
            break;
        }
        if(cnt == middle && !flag) { //直接中位数
            res = temp;
            break;
        }
    }
    return res;
};

O(log(m + n))搞了两个小时搞不出来,算了,,以下是存在漏洞的代码

var findMedianSortedArrays = function (nums1, nums2) {
    let m = nums1.length;
    let n = nums2.length;
    let total = m + n;
    if (total % 2 == 1) {
        let median = getKnum(nums1, nums2, Math.floor(total / 2) + 1);
        return median;
    } else {
        // let res1 = getKnum(nums1, nums2, total / 2);
        // let res2 = getKnum(nums1, nums2, total / 2 + 1);
        // console.log(res1, res2);
        let median = (getKnum(nums1, nums2, total / 2) + getKnum(nums1, nums2, total / 2 + 1)) / 2;
        return median;
    }
};
function getKnum(nums1, nums2, k) {
    //注意这边操作数组不能修改元素组,因此先进行深拷贝
    let s1 = JSON.stringify(nums1);
    let s2 = JSON.stringify(nums2);
    let n1 = JSON.parse(s1);
    let n2 = JSON.parse(s2);

    while (true) {
        console.log(k);

        if (n1.length == 0) {
            console.log(k, n2[k - 1]);
            return n2[k - 1];
        }
        if (n2.length == 0) {
            console.log(k, n1[k - 1]);
            return n1[k - 1];
        }
        if (k == 1) {
            return Math.min(n1[0], n2[0]);
        }
        let index = Math.floor(k / 2) - 1;

        if (n1.length < index) {
            k = k - n1.length;
            for (let i = 0; i < n1.length; i++) {
                n1.shift()
            }

            continue;
        } else if (n2.length < index) {
            k = k - n2.length;
            for (let i = 0; i < n2.length; i++) {
                n2.shift();
            }
            continue;
        }
        if (n1[index] <= n2[index]) {
            for (let i = 0; i <= index; i++) {
                n1.shift();
            }
        } else {
            for (let i = 0; i <= index; i++) {
                n2.shift();
            }
        }
        k = k - Math.floor(k / 2);
        // console.log(n1, n2);
    }

}

let res = findMedianSortedArrays([2, 3, 4, 5, 6], [1]);
console.log(res);

十一、912.排序数组

在这里插入图片描述

1.快速排序

var sortArray = function(nums) {
    quicksort(nums, 0, nums.length - 1);
    return nums;
};

//快速排序
function quicksort(nums, l, r) {
    if(l >= r) return;
    let pivot = nums[l];
    swap(nums, l, r);

    let i = l; 
    for(let j = l; j < r; j++) {
        if(nums[j] < pivot) {
            swap(nums, i, j);
            i++;
        }
    }
    swap(nums, i, r); //换回轴值
    quicksort(nums, l, i - 1);
    quicksort(nums, i + 1, r);
}
function swap(nums, i, j) {
    let temp = nums[i];
    nums[i] = nums[j];
    nums[j] = temp;
}

2.堆排序

var sortArray = function(nums) {
    let res = heapSort(nums);
    return res;
};

//堆排序(最小堆)
function heapSort(nums) {
    if(nums.length <= 1) return nums;
    let heapSize = nums.length;
    //建堆
    buildHeap(nums, heapSize);
    //排序
    let res = [];
    for(let i = 0; i < nums.length; i++) {
        res.push(nums[0]); //获取最小元素
        swap(nums, 0, --heapSize);
        siftdown(nums, 0, heapSize);
    }
    return res;

}

function buildHeap(nums, heapSize) {
    for(let i = Math.floor(heapSize/2) - 1; i >= 0; i--) {
        siftdown(nums, i, heapSize);
    }
}
function siftdown(nums, i, heapSize) {
    let smallest = i; 
    let left = 2*i + 1;
    let right = 2*i + 2;

    if(left < heapSize && nums[left] < nums[smallest]) {
        smallest = left;
    }
    if(right < heapSize && nums[right] < nums[smallest]) {
        smallest = right;
    }
    if(smallest != i) {
        swap(nums, i, smallest);
        siftdown(nums, smallest, heapSize);
    }
}
function swap(nums, i, j) {
    let temp = nums[i];
    nums[i] = nums[j];
    nums[j] = temp;
}

3.归并排序

var sortArray = function(nums) {
    let res = mergeSort(nums);
    return res;
};
//归并排序
function mergeSort(nums) {
    if(nums.length <= 1) return nums;
    let middle = Math.floor(nums.length/2);
    let arr1 = nums.slice(0, middle);
    let arr2 = nums.slice(middle);
    return merge(mergeSort(arr1), mergeSort(arr2));
}
function merge(arr1, arr2) {
    let res = [];
    while(arr1.length > 0 && arr2.length > 0) {
        if(arr1[0] <= arr2[0]) {
            res.push(arr1.shift());
        } else {
            res.push(arr2.shift());
        }
    }
    return res.concat(arr1).concat(arr2);
}

十二、70.爬楼梯

在这里插入图片描述

超时的:

/**
 * @param {number} n
 * @return {number}
 */
var climbStairs = function(n) {
    let res = 0;
    function cnt(n) {
        if(n < 0) return;
        if(n == 0) {
           res++; 
           return;
        }
        //迭代(递归)
        // +1
        cnt(n - 1);
        // +2
        cnt(n - 2);
    }
    cnt(n);
    return res;
};

动态规划

var climbStairs = function(n) {
    //f(n) = f(n - 1) + f(n - 2)
    if(n == 1) return 1;
    if(n == 2) return 2;

    let n1 = 1;
    let n2 = 2;
    let sum = 0;
    for(let i = 3; i <= n; i++) {
        sum = n1 + n2;
        n1 = n2;
        n2 = sum;
    }
    return sum;
};

十三、61.旋转链表

在这里插入图片描述

/**
 * Definition for singly-linked list.
 * function ListNode(val, next) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.next = (next===undefined ? null : next)
 * }
 */
/**
 * @param {ListNode} head
 * @param {number} k
 * @return {ListNode}
 */
var rotateRight = function(head, k) {
    if(!head || !head.next || k === 0) return head;
    //首先算出链表的长度n 并且闭合为环
    let n = 1;
    let curr = head;
    while(curr.next) {
        curr = curr.next;
        n++;
    }
    

    //开始计数断开环 并返回结果
    let add = n - k % n;
    if(add === n) return head; //特殊情况

    curr.next = head; //注意要在后面成环 不然上面特殊情况返回的是一个环

    while(add) {
        curr = curr.next;
        add--;
    }

    const res = curr.next;
    curr.next = null;
    return res;
};

十四、剑指offer 22.链表中倒数第k个节点

在这里插入图片描述
这个用闭合为环会超时

/**
 * Definition for singly-linked list.
 * function ListNode(val) {
 *     this.val = val;
 *     this.next = null;
 * }
 */
/**
 * @param {ListNode} head
 * @param {number} k
 * @return {ListNode}
 */
var getKthFromEnd = function(head, k) {
    //双指针做法
    let left = head;
    let right = head;
    //右指针先走k步
    for(let i = 0; i < k; i++) {
        right = right.next;
    }
    //左右指针同时走 直到right === null
    while(right) {
        left = left.next;
        right = right.next;
    }
    return left;
};

十五、46.全排列

在这里插入图片描述
回溯法:

/**
 * @param {number[]} nums
 * @return {number[][]}
 */
var permute = function(nums) {
    const res = [];
    const used = {};
     
    function dfs(path) {
        if(path.length === nums.length) {
            res.push(path.slice());
            return;
        }
        for(let k of nums) {
            if(used[k]) continue; //已经使用过
            path.push(k);
            used[k] = true;
            dfs(path);
            path.pop(); //回到上一层
            used[k] = false;
        }
    }

    dfs([]);
    return res;
};

十六、剑指offer 38.字符串的排列

在这里插入图片描述

/**
 * @param {string} s
 * @return {string[]}
 */
var permutation = function(s) {
    let res = [];
    let used = {};

    function dfs(str) { //回溯
        if(str.length === s.length) {
            res.push(str);
            return;
        }
        for(let i = 0; i < s.length; i++) {
            if(used[i]) { //已经使用过
                continue;
            }
            used[i] = true;
            dfs(str + s[i]);
            used[i] = false;
        }
    }
    dfs("");
    res = Array.from(new Set(res)); //去重
    return res;
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值