又回到最初的起点,来回顾一下两数之和怎么计算|刷题打卡

392 阅读2分钟

这次,我决定回顾一下我在leetcode上做的第一题,看了下提交记录,没想到已经是两年前了。

原题链接: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]

提示:

  • 2<=nums.length<=1032 <= nums.length <= 10^3
  • 109<=nums[i]<=109-10^9 <= nums[i] <= 10^9
  • 109<=target<=109-10^9 <= target <= 10^9
  • 只会存在一个有效答案

二、整理思路

依稀记得第一次做的时候用的是暴力法遍历了两次,然后超时了。这次拿到手之后,想了一下,直观的解法还是遍历,但是不用两次,而是用indexOf来替代遍历,同时通过条件进行剪枝,一次通过了测试用例。

第一步:

确认输入输出:

输入:一个数组;输出:一个数组。

第二步

怎么处理输入才能得到输出?

既然要找配对的元素,那么至少需要一次遍历,优化的难点就在于,怎么减少遍历的数量。

初步的写法是通过剪枝来优化:

/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number[]}
 */
var twoSum = function(nums, target) {
    let res=[]
    for(let i=0;i<nums.length;i++){
        //无论是大于还是小于都可以,只是为了减少一半的计算量
        if(target-nums[i]<=nums[i]){
            let idx=nums.indexOf(target-nums[i])
            //由于用的是indexOf,有可能找到自己
            //所以一定要加下标判断
            if(i!=idx&&idx>=0){ res=[i,idx]}
        }
    }
    return res
};

剪枝之后,计算的速度提升了不少,至少不会超时了。不过依稀觉得这依然不是最好的方法,于是参考了一下题解,看完恍然大悟,用Map才是最好的选择。

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

使用Map来进行下标的记录和查找,既不用担心找到本身,也减少了内存的消耗,更重要的是,代码思路一目了然。

三、总结

知识点:求和

解题法:剪枝法;哈希表

作为当初入坑leetcode的第一题,时隔两年再做有一些不一样的感受。时光易逝,把握现在把。

本文正在参与「掘金 2021 春招闯关活动」, 点击查看 活动详情