题目要求:
给定一个整数数组和一个目标值,找出数组中和为目标值的两个数。
你可以假设每个输入只对应一种答案,且同样的元素不能被重复利用。
示例:
给定 nums = [2, 7, 11, 15], target = 9因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]
C++代码(8ms):
class Solution {
public:vector<int> twoSum(vector<int>& nums, int target) {unordered_map<int,int> map;int n = (int) nums.size();for(int i = 0; i<n; i++){auto p = map.find(target-nums[i]);if(p!=map.end()){return {p->second,i};}map[nums[i]]=i;}}
};
结果:
穷举法解析:
当然最简单直接和暴力的方法就是迭代2次for循环,
代码理解比较简单,就是对于nums数组里的每个元素,拿它跟后面的元素一一做加法,如果他们两者之和刚好等于target的值,那么就把这两个位置(i,j)push_back进result里面,最后再返回result即可。
但是不可避免地,我们做了很多重复计算,时间复杂度是很高的。
代码如下(192ms):
class Solution {
public:vector<int> twoSum(vector<int>& nums, int target) {vector<int> result;for(int i = 0; i < nums.size();i++){for(int j = i+1;j< nums.size();j++){if(nums[i]+nums[j] == target){result.push_back(i);result.push_back(j);break;}}}return result;}
};
较优解法解析:
而我们的8ms的代码用到了unordered_map,即无序映射,它是关联容器,用于存储由键值和映射值组合而成的元素,并允许基于键快速检索各个元素,很类似python里面的list。
不懂的朋友可以看这篇博文:unordered_map的用法
因此首先我们创建一个unordered_map的对象map,其key和value类型均是int型的
unordered_map<int, int> map;
然后我们对于nums数组里的每个元素遍历,(注意,之前穷举法是,不管找没找到,全部元素都遍历完,而我这边找完就截止查找,所以时间复杂度就低了,因为没必要做无谓的多余的查找)
for (int i = 0; i < n; i++) {
这里建立的unordered_map,其key就是实际的值,也就是nums[i]对应的值,比如题目中的2、7、11、15,而value就是2、7、11、15所在的位置,如0、1、2、3(目的就是通过求出target-nums[i],是否在我们之前保存的unordered_map里面)
之后通过map.find查找,找到了就返回一个iterator值,并保存在p变量,找不到则返回map.end()
auto p = map.find(target-nums[i]);
如果找到了,也就是
if (p!=map.end()) {
那么就返回2个数的位置,第一个数就是p这个iterator的second,也就是它的value,因为value存的就是位置,然后第二个数就直接返回i即可
return {p->second, i};
如果找不到,那么就把当前这个数和他的位置存入unordered_map中,比如我的第一个元素是2,最开始unordered_map里面当然找不到它对应的target-nums[i]也就是9-2=7,所以就把key-2,value-0存入unordered_map里面
那么当我下一个元素是7时,计算target-nums[i]也就是9-7=2,在unordered_map里面去找,找到key-2,所以就返回了p->second也就是p的value,即key-2的value,也就是0,以及当前的i也就是1
map[nums[i]]=i;