转自:http://www.cnblogs.com/dollarzhaole/archive/2013/06/24/3152962.html
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
解题思路:
(1)O(nlogn)。排序,然后两个指针一前一后。因为题中说明了只有一对答案,因此不需要考虑重复的情况。
(2)O(n)。哈希表。将每个数字放在map中,历遍数组,如果出现和数组中的某一个值相加为target的时候,break。这个方法同样适用于多组解的情况。
(1)先排序,后搜索查找
struct Node { int num, pos; }; bool cmp(Node a, Node b) { return a.num < b.num; } class Solution { public: vector<int> twoSum(vector<int> &numbers, int target) { // Start typing your C/C++ solution below // DO NOT write int main() function vector<int> result; vector<Node> array; for (int i = 0; i < numbers.size(); i++) { Node temp; temp.num = numbers[i]; temp.pos = i; array.push_back(temp); } sort(array.begin(), array.end(), cmp); for (int i = 0, j = array.size() - 1; i != j;) { int sum = array[i].num + array[j].num; if (sum == target) { if (array[i].pos < array[j].pos) { result.push_back(array[i].pos + 1); result.push_back(array[j].pos + 1); } else { result.push_back(array[j].pos + 1); result.push_back(array[i].pos + 1); } break; } else if (sum < target) { i++; } else if (sum > target) { j--; } } return result; } };
算法中的sort的时间复杂度:http://blog.csdn.net/leo115/article/details/8654294(sort详细讲解)
stl <algorithm> 中的sort算法实现,采用快排的思想,平均的时间复杂度是 N(logN);算法中还提供了其他的集中排序函数 sort_heap() stable_sort() 时间复杂度都在 N(logN)
(2)哈希(转自:http://blog.csdn.net/jiadebin890724/article/details/23305449)
思路是循环一次,每次都判断当前数组索引位置的值在不在hashtable里,不在的话,加入进去,key为数值,value为它的索引值;接下来再在hashtable中查找(target-当前数值)这个数,利用了hashtable中查找元素时间为常数的优势,如果找到,取得他的key,记为n(此时n一定小于循环变量i,如输入2,3,4,target=6,判断2的时候4还没加载进来,所以继续循环,到4的时候,找了前边的2)。此处需要注意的是,如果数组中有重复的值出现,那么第二次出现时就不会加入到hashtable里了,比如3,4,3,6;target=6时,当循环到第二个3时,也可以得到正确结果。
class Solution {
public:
vector
twoSum(vector
&numbers, int target) {
int i, sum;
vector
results;
map
hmap;
for(i=0; i
(numbers[i], i)); } if(hmap.count(target-numbers[i])){ int n=hmap[target-numbers[i]]; if(n
总结:读完题首先想到的就是两层遍历法,但是显然时间复杂度太高,是O(N^2),不符合要求,于是就应该想如何降低复杂度,首先应该想将逐个比较转变为直接查找,即首
先计算出 target与当前元素的差,然后在序列中寻找这个差值,这样首先就把问题简化了,而
寻找的过程可以先对序列进行快排,然后二分查找,这样整体的复杂度就降低为 O(N*logN) 了;
查找最快的方法是利用一个 map容器存储每个元素的索引,这样取得某个特定元素的索引只需要常数时间即可完成,这样就更快了,最多只需遍历一次序列,将元素及其索引加入map中,在遍历的过程中进行对应差值的查找,如果找到了就结束遍历,这样时间复杂度最多为 O(N),It's amazing!
本来想用C++的hash_map,后来发现STL并没有这个容器,貌似需要自己实现代码才能用,遂用map了,
map底层使用红黑树实现的,所以它的查找时间是O(logN),略逊于hash_map,但是这不是绝对的,hash_map虽然理论上是O(N),其实他还有计算hash值的时间消耗,也存在时间比O(logN)还大的时候(在一篇博客里看到的)。
ps:自己的
#include
#include
#include
要注意重复的输入且结果就是重复输入的两数之和和 map找的是自己,自己加自己的情况