Given an array of integers, find two numbers such that they add up to a specific target number.
The function twoSum should return indices of the two numbers such that they add up to the target, where index1 must be less than index2. Please note that your returned answers (both index1 and index2) are not zero-based.
You may assume that each input would have exactly one solution.
Input: numbers={2, 7, 11, 15}, target=9
Output: index1=1, index2=2
solution:暴力算法很显然是O(n2)会超时。
那么我的做法是把数组排序后二分查找。这样是O(n*lgn)。这里注意一个细节是类内的cmp比较函数要定义成静态成员函数,不然sort调用时会报错:invalid use of non-static member function。因为非静态成员函数是依赖于具体对象的,而std::sort这类函数是全局的,因此无法再sort中调用非静态成员函数。静态成员函数或者全局函数是不依赖于具体对象的, 可以独立访问,无须创建任何对象实例就可以访问。同时静态成员函数不可以调用类的非静态成员。
还有discuss里有更好的O(n)算法,就是hash的思想,利用unordered_map这一无序map来使查找的时间接近常数。unordered_map和map的区别是它无序,所以在不需要排序时最好使用它,比map更快。
class Solution { public: struct node{ node(int i,int v):id(i),val(v){} int id,val; }; static bool cmp(node a,node b){ return a.val<b.val; } vector<int> twoSum(vector<int>& nums, int target) { vector<node>vt; vector<int>ans; vector<int>::iterator it; int a1=0,a2=1; for(it=nums.begin();it!=nums.end();it++){ vt.push_back(node(++a1,*it)); } sort(vt.begin(),vt.end(),cmp); a1=0; for(it=nums.begin();it!=nums.end();it++){ int t=*it; a1++; a2=lower_bound(vt.begin(),vt.end(),node(0,target-t),cmp)-vt.begin(); int a3=upper_bound(vt.begin(),vt.end(),node(0,target-t),cmp)-vt.begin(); if(a2<vt.size()&&a2==a3&&vt[a2].val==target-t&&vt[a2].id>a1){ a2=vt[a2].id; //printf("index1=%d, index2=%d\n",a1,a2); ans.push_back(a1); ans.push_back(a2); return ans; } else if(a2<vt.size()&&vt[a2].val==target-t&&a2<a3){/*这个处理很有必要,不然[0,4,3,0]和target=0 这组数据会WA,二分时要注意考虑有几个相等的情况*/ for(int i=a2;i<a3;i++){ if(vt[i].id>a1){ ans.push_back(a1); ans.push_back(vt[i].id); return ans; } } } } return ans; } };
my answer
vector<int> twoSum(vector<int> &numbers, int target) { //Key is the number and value is its index in the vector. unordered_map<int, int> hash; vector<int> result; for (int i = 0; i < numbers.size(); i++) { int numberToFind = target - numbers[i]; //if numberToFind is found in map, return them if (hash.find(numberToFind) != hash.end()) { //+1 because indices are NOT zero based result.push_back(hash[numberToFind] + 1); result.push_back(i + 1); return result; } //number was not found. Put it in the map. hash[numbers[i]] = i; } return result; }
better answer in discuss