【为进大厂力扣刷题】1. 两数之和

138 阅读2分钟

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

一、题目描述:

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 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]

进阶: 你可以想出一个时间复杂度小于 O(n2) 的算法吗?

二、思路分析:

先分析一下示例,1、2表明了原理,任意两项合为目标值即可。示例3说明了结果两项索引不能一致,既不能[0, 0],[1, 1]。

看到题目,我首先想到的就是循环嵌套,直接动手,先解决问题再说优化的事情。

解法1

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

1647267292(1).png

通过是通过了,排名有点说不过去,时间内存都不占优。

目前以我理解,算法就是时间和空间的博弈

  • 想要时间快,就少遍历,用内存去保存一些数据。
  • 想要内存少,只能多遍历,不去多保存数据。

这里涉及到了复杂度 数组的长度是n,循环了两边,时间复杂度是 O(n^2)*

声明了变量i 和 j ,这两个变量不会随着数组长度的增长而变化。所以就是最低的O(1)

时间复杂度指算法大概执行了多少遍

空间复杂度指运行算法时,需要多少额外的内存空间

解法2

既然解法1用了双重遍历,时间复杂度拉满,那这次想着用空间去换一些时间。具体就是只遍历一次,然后用变量去存一下历史数据,如果历史数据和当前数据匹配则返回。

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

1647269471(1).png

这次时间复杂度仅为O(n),排名一下上来了,但空间复杂度也变成了O(n),因为Obj可能遍历到数组最后一项才返回结果。典型的空间换时间。

再稍微优化一下,存一下变量,省的多次去取,最终形态

var twoSum = function(nums, target) {
    let obj = {}
    for(let i=0; i<nums.length; i++){
        let v = nums[i]
        let key = target - v
        if(key in obj){
            return [obj[key], i]
        } else {
            obj[v] = i
        }
    }
};

1647270116(1).png

OK啦,今儿第一题算圆满完成,明儿再见!!!!