前言
又是一年春招季,回想去年这个时候自己还在苦哈哈的刷面经投简历找实习,一眨眼一年过去了,回想2020,最大的收获可能就是对找工作这件事情上积累了一丢丢经验,但是找到工作不是最终目的,提升自己的能力才最重要。
处于面试的阶段中,可能对面试常见的题目、算法过程和思路都有比较深刻的记忆,因为面试总是在问这些内容,但是因为遗忘的存在,一旦不再每天都重复记忆这些知识点,很快就会遗忘。所以最好的方式就是用文字的方式记录下来,方便日后复习。
今天就来讲讲leetcode
上的经典算法题-towSum
,本人在前期面试过程中没有遇到过这个算法题,所以尽管在别的面经中看到过也没有在意,但是后来陆续在快手
微软
的面试中都问到了,所以对这道算法要足够重视。
题目描述
给定一个整数数组
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]
提示
- 2 <= nums.length <= 103
- -109 <= nums[i] <= 109
- -109 <= target <= 109
- 只会存在一个有效答案
解题思路
首先分析题目:给定一个数组,从数组中找到两个数,满足两数之和等于给定的目标值,而且数组中的数字不能重复使用,同时这样的两个数一定存在
如果不考虑时间复杂度,那么双重循环可以解决问题,代码:
var forceFind = function(nums, target) {
let l = nums.length, flag = false;
let res = [];
for(let i = 0; i < l; i++) {
if (flag) {
break;
}
for(let j = 0; j < l; j++) {
if (i !== j && nums[i] + nums[j] === target) {
res.push(i);
res.push(j);
flag = true;
break;
}
}
}
return res;
}
执行结果:
暴力求解的问题在于使用了双重循环,时间复杂度为
O(n^2)
,在实际面试中这样的回答不能让面试官满意
有没有办法在O(n)
的时间内完成计算呢?
当然是有的,就是用空间换时间的方式来实现,具体就是借助map
来实现。具体为:通过初始化一个map
,遍历数组,判断map
中是否存在与当前遍历的值想加和为目标值的数字,如果有,那么就直接返回结果;否则就把当前数字存到map
中,存储的方式为map[arr[index]]=index
,也就是key
为当前值,value
为当前索引,具体代码实现为:
var forceFind = function(nums, target) {
let l = nums.length;
let res = [];
let map = new Map();
for(let i = 0; i < l; i++) {
if (map.has(target-nums[i])) {
res.push(map.get(target-nums[i]));
res.push(i);
break;
} else {
map.set(nums[i], i);
}
}
return res;
}
这种方式的好处在于降低了时间复杂度,不必对数组进行排序,也不必进行多次遍历,一次遍历找到答案。
说明:通过map[arr[index]]=index
的方式存储,如果数组中有重复数字,那么后面的会覆盖前面的,这样不会影响最终结果,所以在题目没有约束的情况下不用考虑这一点
总结
如果这篇文章对你有帮助的话,就请点赞、关注吧
本文正在参与「掘金 2021 春招闯关活动」, 点击查看 活动详情