[hashmap|空间换时间] leetcode 1 两数之和
1.题目
题目链接
给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那两个整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。
示例:
给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]
2.分析
2.1.第一印象
第一眼的想法为“暴力求解”,即利用两层for循环遍历数组,判断是否有满足条件的数对:
vector<int> twoSum(vector<int>& nums, int target) {
vector<int> res;
for(int i = 0; i < nums.size(); i++) {
for(int j = i + 1; j < nums.size(); j++) {
if(nums[i] + nums[j] == target){
res.push_back(i);
res.push_back(j);
return res;
}
}
}
return res;
}
时间复杂度为O(n2)。能否在此基础上进行改进?
2.2.HashMap
HashMap存储着key-value键值对,一个显著的优势是能够将查找的时间复杂度降为O(1)。
那么本题可以这么理解:对于当前遍历到的数a,只需要判断target - a是否在数组中即可。
此时key就是nums数组中第i个数的值,value就是数组中第i个数的下标(也就是i)。也就是说,同样是寻找一个数,通过构造一个反向的从值到下标的映射,可以压缩查找的时间。
原: 使用内层for循环来判断另一个数是否满足要求
for(int i = 0; i < nums.size(); i++) {
for(int j = i + 1; j < nums.size(); j++) {
//do something...
}
}
改: 使用内层if来以O(1)的时间复杂度判断另一个数是否满足要求
for(int i = 0; i < nums.size(); i++) {
if(map.find(target - nums[i] != map.end())) {
//do something...
}
}
修改后的代码便实现了所谓的空间换时间:用hashmap的 O(n) 的存储效率换取了 O(1) 的查找效率。
3.代码
C++中hashmap以unordered_map的形式实现。
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
unordered_map<int,int> m;
for(int i = 0; i < nums.size(); i++) {
if(m.find(target-nums[i]) != m.end()) {
return {m[target-nums[i]], i};
}
m[nums[i]] = i;
}
return {};
}
};