每日一题:两数之和

161 阅读2分钟

Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情

一、题目描述:

leetcode第一题:两数之和

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

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

nums=[1,2,3,5,0]target=8;那么输出结果应该是[2,3]。因为nums[2]+nums[3] = 3+5 =8

二、思路分析:

  1. 最直接的,我们可以直接两次循环,看两次循环中哪两个数相加可以等于target。当然两次循环的话,复杂度就是0(n²)。另外需要注意题目中一个元素不能同时出现,所有两层循环时,不能取同一个index的元素

  2. 用空间换时间:使用一个对象来映射数组中值。obj={},对数组nums进行一次遍历。每次循环在obj中找当前元素n需要的对应的元素target-n;当target-n不在对象中时,记录当前n和index;在下一次循环中继续判断有没有需要的对应值。相当于这样的:

    • 循环数组,index=0,n=1时,需要target-1=7,在obj中查找有没有obj[7],发现没有,记录当前值和index,赋值obj[1]=0
    • index=1,n=2时,检查obj中有没有obj[target-n]obj[6]发现没有则赋值记录当前index:obj[2]=1
    • index=2,n=3时,index为2的位置需要5,判断有无obj[5],没有,记录赋值obj[3]=2
    • index=3,n=5时,index为3时位置需要3,判断有obj[3],发现有,说明之前出现过3,当前值为5,满足要求,return [obj[3], index][2,3]

三、AC 代码:

/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number[]}
 */
var twoSum = function(nums, target) {
    // 解法一:两层循环
    for(let i=0;i<nums.length;i++){
        for(let j=0;j<nums.length;j++){
            if(i!==j&&nums[i]+nums[j]===target){
                return [i,j]
            }
        }
    }
    // 解法二:定义obj,记录值和index,在循环时找target-n
    let obj={}
    for(let i=0;i<nums.length;i++){
        let n = nums[i]
        if(target-n in obj){ // 若值为0也是true;undefined才为false
           // 表示找到了对应的两个值,当前值的index为i,对应值的index:obj[target-n]
            return [obj[target-n], i]
        }else{
           // 没有找到对应值,则记录当前值和index
            obj[n] = i
        }
    }
    // 与解法二类似,我们可以记录当前值和index,同样可以记录需要的值target-n和当前index。表示第index的位置需要值target-n。在循环中查询当前值是不是某个需要的值(在obj中存在)
    let obj={}
    for(let i=0;i<nums.length;i++){
        let n = nums[i]
        if(n in obj){ // 若值为0也是true;undefined才为false
           // 表示找到了对应的两个值,当前值的index为i,对应值的index:obj[n]
            return [obj[n], i]
        }else{
           // 没有找到对应值,则记录当前值的index和需要的值
            obj[target-n] = i
        }
    }
}

四、总结:

在算法思想中,使用空间换时间的思想很常见,上面这个小示例就是。其他情况下我们可以善加利用这种思想。