Problem: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
由于水平问题,本题参考了Suool大神的思路。因为我首先想到的居然是两个for,第一个for全部,第二个for从前一个for的迭代加1开始寻找相等记录下标。
class resolution{ public: vector<int> twoSum(vector<int> &numbers, int target) { vector<int>::iterator iter, res; vector<int> result(2); res = result.begin(); for (iter = numbers.begin();iter != numbers.end();++iter) { for (vector<int>::iterator iter2 = iter + 1;iter2!=numbers.end();++iter2) { if(*iter + *iter2 == target) { *res = iter - numbers.begin() + 1; *(++res) = iter2 - numbers.begin() + 1; return result; } } } } };
可想而知运行超时,于是,冷静参考了Suool后,想了下这是最low的N方复杂度。既然超时,那应该是nlogn能解决的。想到排序吧就nlogn了。那就排序吧。用std::sort。
排序之后那就用头尾之和来判断,不断往里缩进直至找到答案为止。
头尾之和小于target的话,那就头要往前才能增大。
头尾之和大于target的话,那就尾要回缩才能缩小。
因为答案有且仅有一个,所以,不断缩进肯定可以找到答案。
找到到答案后,那就根据key值在原来的vector中找,大不了遍历2n就找到下标,push_back到result中就好了。
class Solution{ public: vector<int> twoSum(vector<int> &numbers, int target) { vector<int> result; vector<int> temp = numbers; std::sort(temp.begin(),temp.end()); int left = 0; int right = temp.size() - 1; int sum = 0; int index = 0; while(left < right) { sum = temp[left] + temp[right]; if (sum == target) { while(true) { if(numbers[index] == temp[left]) { result.push_back(index + 1); } // must be 'else if' or the same index will be push_back when the target is composed by two same numbers else if(numbers[index] == temp[right]) { result.push_back(index + 1); } if(result.size() == 2) { return result; } index++; } } else if (sum < target) { left++; } else { right--; } } } };
这样就行了。注意当中的else if 避免相同的值相加为target的case导致错误记录index。可以吧else if 改成 if 提交看下错误提示就知道了。
有位更叼的大神居然用n就解决了http://www.tuicool.com/articles/RBNjuu
2015/01/08:
今天有个人问我这题,然后说了以上方法,顺带写了个hash的O(n)
class Solution{ public: vector<int> twoSum(vector<int> &numbers, int target){ vector<int> result; unordered_map<int, int> umap; for (int i = 0; i < numbers.size(); i++){ umap[numbers[i]] = i + 1; } for (int i = 0; i < numbers.size(); i++){ int umapVal = umap[target - numbers[i]]; if (umapVal && umapVal != i + 1){ result.push_back(i + 1); result.push_back(umap[target - numbers[i]]); break; } } return result; } };
就是用hash记录每个值的下标,以便于target减去一个值之后可以O(1)时间找到剩下的知否在当前给定的值里。是的话就返回下标return了。
需要注意的是,你要找的剩下的值是否在给定的里面要加一个不是本身的判断,因为例子target = 6, 给定 3, 2, 4 的时候,umap != i + 1 就派上用场了。
2015/04/03:
class Solution { public: vector<int> twoSum(vector<int> &numbers, int target) { unordered_map<int, int> umap; vector<int> ans; for (int i = 0; i < numbers.size(); ++i){ umap[numbers[i]] = i + 1; } for (int i = 0; i < numbers.size(); ++i){ if (umap.count(target - numbers[i]) && i + 1 != umap[target - numbers[i]]){ ans.push_back(i + 1); ans.push_back(umap[target - numbers[i]]); } } return ans; } };