LeetCode热题(JS版) - 1. 两数之和

157 阅读1分钟

题目

给定一个整数数组nums和一个目标值target,请你在该数组中找出和为目标值的那两个整数,并返回他们的数组下标。 你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。 示例1:

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

示例2:

输入: nums = [3,2,4], target = 6
输出: [1,2]

示例3:

输入: nums = [3,3], target = 6
输出: [0,1]

解法1:两层循环

  • 思路

    • 找到第一个可用值a
    • 从后面找和为目标值的数b
    • 如果没找到,那么重新找a,直到成功
  • 时间复杂度:O(n^2)

  • 代码:

function twoSum(nums: number[], target: number): number[] {
    let a, b;
    for(let i = 0; i< nums.length - 1; i++) {
        // 找到一个a
        if(a == null) a = i;
        
        // 找b
        for(let j = a + 1; j < nums.length; j++) {
            if(nums[i] + nums[j] === target) {
                b = j;
                break;
            }
        }
        
        // 找到退出,没找到继续
        if(b != null) break;
        else a = null;
    }
    
    return [a, b];
};

image.png

  • 讨论

写得有点啰嗦,可以简化点:

function twoSum(nums: number[], target: number): number[] {
    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;
};

image.png

解法2:Map缓存索引

  • 思路

    • 先构建一个map
    • 再遍历数组
    • 计算差并在map中找是否存在
  • 时间复杂度:O(2n)

  • 代码

function twoSum(nums: number[], target: number): number[] {
    // 先构建一个map
    // 再遍历数组
    // 计算差并在map中找是否存在
    const map = new Map(nums.map((d, i) => [d, i]));
    for(let i = 0; i < nums.length; i++) {
        const j = map.get(target - nums[i]);
        if(j != null && j !== i) return [i, j]   
    }
    
    return null;
};

image.png

改进下:map在遍历的时候赋值,后面的元素查找之前的元素,就不会重复,性能也会好点O(n)。

function twoSum(nums: number[], target: number): number[] {
    // 先构建一个map
    // 遍历数组时初始化,计算差并在map中找是否存在
    const map = new Map();
    for(let i = 0; i < nums.length; i++) {
        const j = map.get(target - nums[i]);
        if(j != null) return [i, j]  
        else map.set(nums[i], i);
    }
    
    return null;
};

image.png

  • 讨论

用对象会不会好点,对象比map速度慢了,内存小了。综合来看最好。

function twoSum(nums: number[], target: number): number[] {
    // 先构建一个map
    // 遍历数组时初始化,计算差并在map中找是否存在
    const map = {};
    for(let i = 0; i < nums.length; i++) {
        const j = map[target - nums[i]];
        if(j != null) return [i, j]  
        else map[nums[i]] = i;
    }
    
    return null;
};

image.png