这道题和编程之法上面的题目有以下几个不同:
1、题目所给定的数组是无序的,编程之法里面是默认有序的
2、要求输出原数组的序号,如果用一个结构体维护数组下标,那么需要O(n)的空间,显然不是最好的方法
3、题目中包含负数,之前想用数值直接表示数组下标,数组值为原来的真正数组下标,但是由于是负数,所以这个方法也失效了
4、有重复数值,同样是之前的用数组来存储原数组下标的方法,在出现了重复数值后,就会发生冲突
所以这道题最好的解决方法就是使用一个map,因为数组有越界的危险,而map中的key关键值没有,可以很好解决负数的问题,而且关键字要求是唯一的,所以也顺便解决了重复数值的问题
相同的数值所对应的关键字Key是不同的 ,因此重复数值就可以通过关键字来区别。注意:题中的key直接用for循环中的i来表示,i是不断自增的,所以不会重复。
/*
为了提高时间的复杂度,需要用空间来换,要用线性的时间复杂度来解决问题,就是说只能遍历一个数字,那么另一个数字,可以事先将其存储起来,
使用一个Map,来建立数字和其坐标位置之间的映射,Map是常数级的查找效率,这样,我们在遍历数组的时候,用target减去遍历到的数字,就是另一个需要的数字了
直接在HashMap中查找其是否存在,注意要判断查找到的数字不是第一个数字
*/
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
map<int, int> m;
vector<int> res;
for (int i = 0; i < nums.size(); ++i) {
m[nums[i]] = i;
}
for (int i = 0; i < nums.size(); ++i) {
int t = target - nums[i];
if (m.count(t) && m[t] != i) {
//map有两种查找方式,一种是使用find()函数查找,另一种是这里使用的索引查找,不过这种方式要求该索引一定存在,否则会导致程序崩溃
//m[t]为原数组中索引值为t所对应的最大的原数组下标(关键字key),i为当前数组下标,只要m[t]!=i,就可以保证所要判断查找的数字不是第一个数字(自身)
res.push_back(i);
res.push_back(m[t]);
break;
}
}
return res;
}
};