算法集合

187 阅读3分钟

1.两数之和

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target  的那 两个 整数,并返回它们的数组下标。

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。

你可以按任意顺序返回答案。

输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1]

方案一:map

var twoSum = function (nums, target) {
    let map = new Map();
    for (let i = 0; i < nums.length; i++) {
        if (map.has(target - nums[i])) {
            return [map.get(target - nums[i]), i]
        } else {
            map.set(nums[i], i)
        }
    }
    return null;
};

方案二:遍历

var twoSum = function (nums, target) {
    for (let i = 0; i < nums.length - 1; i++) {
        for (let j = i + 1; j < nums.length; j++) {
            if (nums[i] + nums[j] === target) {
                return [i, j]
            }
        }
    }
    return null
};

15.三数之和

给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。

注意:答案中不可以包含重复的三元组。

输入: nums = [-1,0,1,2,-1,-4]
输出: [[-1,-1,2],[-1,0,1]]

方案一:双指针

var threeSum = function (nums) {
    nums.sort((a, b) => a - b); // 排序
    const res = [];
    // i遍历到len - 2即可,因为k指针指向len - 1这个元素,相当于nums[len - 1]作为固定值被遍历了一遍
    for (let i = 0; i < nums.length - 2; i++) { // 外层遍历
        let n1 = nums[i];
        if (n1 > 0) break; // 如果已经爆0,不用做了,break
        // 如果当前固定的数与前一个相等,则说明已经寻找过这种情况了不需要再找一遍
        if (i > 0 && n1 == nums[i - 1]) continue; // 遍历到重复的数,跳过    
        let left = i + 1;            // 左指针
        let right = nums.length - 1; // 右指针
        while (left < right) {
            let n2 = nums[left], n3 = nums[right];
            if (n1 + n2 + n3 === 0) {  // 三数和=0,加入解集res
                res.push([n1, n2, n3]);
                while (left < right && nums[left] == n2) left++; // 直到指向不一样的数
                while (left < right && nums[right] == n3) right--; // 直到指向不一样的数
            } else if (n1 + n2 + n3 < 0) { // 三数和小于0,则左指针右移
                left++;
            } else {      // 三数和大于0,则右指针左移
                right--;
            }
        }
    }
    return res;
};

88.合并两个有序数组

给你两个按 非递减顺序 排列的整数数组 nums1nums2,另有两个整数 mn ,分别表示 nums1nums2 中的元素数目。

请你 合并 nums2nums1 中,使合并后的数组同样按 非递减顺序 排列。

注意:最终,合并后数组不应由函数返回,而是存储在数组 nums1 中。为了应对这种情况,nums1 的初始长度为 m + n,其中前 m 个元素表示应合并的元素,后 n 个元素为 0 ,应忽略。nums2 的长度为 n

输入:nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
输出:[1,2,2,3,5,6]
解释:需要合并 [1,2,3][2,5,6] 。
合并结果是 [1,2,2,3,5,6] ,其中斜体加粗标注的为 nums1 中的元素。

方案一: 先合并再排序

var merge = function (nums1, m, nums2, n) {
    for (let i = 0; i < n; i++) {
        nums1[m] = nums2[i];
        m++;
    }
    nums1.sort((a, b) => a - b);
    return nums1;
};

方案二: 双指针/从后到前

var merge = function (nums1, m, nums2, n) {
    let p1 = m - 1;
    let p2 = n - 1;
    let p = m + n - 1
    while (p2 >= 0) {
        nums1[p--] = nums1[p1] > nums2[p2] ? nums1[p1--] : nums2[p2--];
    }
    return nums1;
};

217.存在重复元素

给你一个整数数组 nums 。如果任一值在数组中出现 至少两次 ,返回 true ;如果数组中每个元素互不相同,返回 false 。

输入:nums = [1,2,3,4]
输出:false
输入:numn = [1,2,3,1]
输出:true

方案一:

var containDuplicate = function(nums){
    let map = new Map()
    for(i in nums){
        if(map.has(i)){
            return true
        }else {
            map.set(i,1)
        }
    }
    return false
}

方案二:

var containDuplicate = function(nums){
    let arr = [...new Set(nums)]
    return nums.length === arr.length ? false : true
}

509.斐波那契数

斐波那契数 (通常用 F(n) 表示)形成的序列称为 斐波那契数列 。该数列由 0 和 1 开始,后面的每一项数字都是前面两项数字的和。也就是:

F(0) = 0F(1) = 1
F(n) = F(n - 1) + F(n - 2),其中 n > 1

给定 n ,请计算 F(n) 。

输入: n = 2
输出: 1
解释: F(2) = F(1) + F(0) = 1 + 0 = 1

题解:

方案一:递归

var fib = function (n) {
    return n < 2 ? n : fib(n - 1) + fib(n - 2)
};

方案二:动态规划

var fib = function (n) {
    if (n < 2) {
        return n
    }
    let p = 0, q = 1, r, i = 2
    while (i <= n) {
        i++;
        r = p + q;
        p = q;
        q = r;
    }
    return r;
};

104.二叉树最大深度

给定一个二叉树,找出其最大深度。

二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。

说明: 叶子节点是指没有子节点的节点。

示例: 给定二叉树 [3,9,20,null,null,15,7]

    3
   / \
  9  20
    /  \
   15   7

返回它的最大深度 3

题解:

/**
 * 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 {number}
 */
var maxDepth = function(root) {
     if(!root) {
        return 0;
    } else {
        const left = maxDepth(root.left);
        const right = maxDepth(root.right);
        return Math.max(left, right) + 1;
    }
};