【算法-LeetCode】1. 两数之和(Map)

LeetCode1. 两数之和

更新:2021年7月20日16:43:59

问题描述及示例

给定一个整数数组 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]

提示:
2 <= nums.length <= 104
-109 <= nums[i] <= 109
-109 <= target <= 109
只会存在一个有效答案

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/two-sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

我的题解

我的题解1(双层for循环)

总体思路是使用双层for循环来对数组进行遍历,指针i指向第一个加数,指针j指向第二个加数。外层循环用于在固定i值,同时内层循环用于逐个匹配j值。当满足nums[i] + nums[j] === target时,可以立即返回结果。

/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number[]}
 */
var twoSum = function(nums, target) {
	// i 用于固定第一个加数
    for(let i = 0, length = nums.length; i < length; i++) {
    	// j 用于逐个匹配第二个加数
        for(let j = i+1; j < length; j++) {
            if(nums[i] + nums[j] === target) {
                return [i, j];
            }
        }
    }
};

提交记录
54 / 54 个通过测试用例
状态:通过
执行用时: 128 ms,在所有 JavaScript 提交中击败了25.27%的用户
内存消耗: 38.5 MB,在所有 JavaScript 提交中击败了56.91%的用户
时间:202172016:48:00

我的题解2(单层for循环)

上面的题解中用了双层for循环,时间复杂度为O(n^2),下面的题解中只用了一层for循环,我以为最后的表现会好很多,结果发现似乎并没有太多的提升。我猜想可能是includes函数的实现中其实也用到了for循环或者类似的思路,所以导致运行时间增加,但是内存消耗稍稍减小了。

/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number[]}
 */
var twoSum = function(nums, target) {
    let temp;
    for(let i = 0, length = nums.length; i < length; i++) {
        temp = target - nums[i];
        // 注意下面的判断,不能光判断是否包含temp,还要求temp的下标不能和i的一样,
        // 否则像[3,2,4], 6这样的用例就无法返回正确结果
        // (预期返回:[1,2] 实际返回:[0,0])
        if(nums.includes(temp) && nums.indexOf(temp) !== i) {
            return [i, nums.indexOf(temp)];
        }
    }
};

提交记录
54 / 54 个通过测试用例
状态:通过
执行用时: 172 ms,在所有 JavaScript 提交中击败了11%的用户
内存消耗: 38.1 MB,在所有 JavaScript 提交中击败了70%的用户
时间:202172017:41:53

我的题解3(利用Map

更新:2021年8月10日19:41:52

整体思路是用一个Map类型的变量map存储按情况存储nums的下标和其元素值,其中,nums[i]作为mapkey,而i作为相应的的value。因为这样就可以比较方便地使用map中的has()函数来判断map中是否包含某个元素值。

在遍历nums数组时,先判断map中是否包含值为target - nums[i]的数组元素,如果有,则将该元素的下标和当前遍历的元素下标作为返回值返回。注意题目里说了可以假设每种输入只会对应一个答案,所以这里是可以直接返回的,若是有多组答案,则还要进行后续遍历和判断,当然相应的逻辑也要有所改变。

如果map中没有包含值为target - nums[i]的数组元素,则使用set()方法将当前遍历元素放入map中。

当数组遍历完后仍然没有匹配到合适的元素(也就是map中已经被加入了所有的nums中的元素),那么就要按题目要求返回空数组,当然如果nums一开始就为空,那么经过for中的判断后也会触发最后的返回。

/**
 * @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++) {
    // 如果map中能匹配到与当前遍历的数组元素值之和的元素,则可以直接将相应结果返回
    if(map.has(target - nums[i])) {
      return [i, map.get(target - nums[i])];
    }
    // 如果没有相应的匹配,那么则将当前遍历数组存入map
    map.set(nums[i], i);
  }
  // 如果nums为空或者不存在符合条件的两个元素,则返回空数组
  return [];
};


提交记录
54 / 54 个通过测试用例
状态:通过
执行用时:72 ms, 在所有 JavaScript 提交中击败了92.92%的用户
内存消耗:40.2 MB, 在所有 JavaScript 提交中击败了17.73%的用户
时间:2021/08/10 19:33

可以看到,利用Map类型的变量存储相关的下标和元素值之后,在时间表现上有了比较大的提升。但是在空间方面的表现还是不好。

其实我还想过也参照【【算法-LeetCode】15. 三数之和_赖念安的博客-CSDN博客】中的双指针的写法,但是用这种方法需要先将数组排序,而排序后将会打乱数组元素原有的下标,这样就无法返回正确的结果,而在三数之和的题目中是不需要考虑这个的。当然如果用map存储原来的数组元素和下标的对应值,也许也能行得通,但是相比于上面题解3中的做法,那样无疑是绕了一个弯,徒劳增加了时间消耗和空间消耗,显得很没必要。

【更新结束】

官方题解

更新:2021年7月29日18:43:21

因为我考虑到著作权归属问题,所以【官方题解】部分我不再粘贴具体的代码了,可到下方的链接中查看。

更新:2021年7月29日20:00:10

参考:两数之和 - 两数之和 - 力扣(LeetCode)

【更新结束】

有关参考

更新:2021年7月20日16:26:48
参考:Array.prototype.map() - JavaScript | MDN

参考:parseInt - JavaScript | MDN

参考:Number.parseInt() - JavaScript | MDN

参考:JS深入理解—探索parseInt函数_LS.Yu.大前端-CSDN博客

参考:JavaScript Array map() 方法 | 菜鸟教程
参考:Array.prototype.indexOf() - JavaScript | MDN
更新:2021年7月20日17:49:35
参考:JS 中数组常用方法以及它的原理实现(三)
更新:2021年8月10日20:14:45
参考:Map.prototype.get() - JavaScript | MDN
参考:【微信公众号:三分钟学前端 2021-07-27】每日算法:两数之和
参考:JavaScript forEach() 方法 | 菜鸟教程

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值