LeetCode No1题解。两数之和
ps:题目,给定一个整数数组和一个目标值,请你在数组中找出和为目标值的两个数的下标。假设返回的答案仅有一对且同一个整数不可以重复使用。
这是LeetCode开篇第一题,大部分人应该都刷过这道题。我是为了找工作才刷的LeetCode,也就一个月。开始做的时候,看了看题解也就过去了,后来在华为北研所的面试时手撕代码就是这道题。果然欠的账总是要还的。面试官和我说他特别喜欢这道题,既可以暴力简单解决,又可以完美优化。小伙伴们注意你要是面试华为北研所很可能遇到这个问题哟
下面详讲三种思路
第一种,暴力简单解决
思路:很简单,就是用两个for循环去挨个试,过于简单不赘述了。时间复杂度O(n^2)
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
for(int i=0;i<nums.size();++i){
for(int j=0;j<nums.size();++j){
if(i!=j && nums[i] + nums[j] == target){
return {i,j};
}
}
}
return {};//Leetcode 中末尾必须有返回return,否则报错
}
};
补充说明一下,因为是返回数组下标,所以需要考虑按顺序返回。此时i定是小于j的,因为他是按数组顺序查找,定住i值,j从头遍历。
第二种,使用key-value 映射,两次遍历
思路:使用c++提供的STL库中的unordered_map。因为此处不需要排序,所以使用unordered会使建立映射时的性能提高。时间复杂度O(n)。
总共进行两次遍历:
- 第一次遍历,用于建立映射,key是数组内整数,value是该整数的下标。
- 第二次遍历,根据建立好的映射关系,去寻找符合的两个整数。
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
unordered_map<int,int> rec;
for(int i=0;i<nums.size();i++){
rec[nums[i]] = i;
}
for(int i=0;i<nums.size();i++){
if(rec.find(target-nums[i]) != rec.end() && rec[target-nums[i]] != i)
return {i , rec[target-nums[i]]};
}
return {};
}
};
第三种,使用key-value 映射,一次遍历
思路:仔细观察第二种解法,他是使用两次遍历,第一次是建立映射关系,第二次是寻找目标值对,那么优化的思路就很清晰,就是采用一次遍历即建立映射关系同时又寻找目标值对。时间复杂度同上O(n)。
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
unordered_map<int,int> res;
int num = (int)nums.size();
for(int i = 0;i<num;++i){
unordered_map<int,int>::iterator pos = res.find(target - nums[i]);
if(pos != res.end() && pos->second != i){
return {pos->second,i};
}
else{
res[nums[i]] = i;
}// if...else
}//for
return{};
}
};
限于自己水平,也不知道是否给大家讲清楚和漏掉重要的东西,若是有错误或者疑惑的地方随时欢迎私信。