练习1-39是简单题目,练习40开始做中级题目。
找到一个序列中的两个序号,要求该序号对应的两个数和为指定值。
【思路】
1.暴力解决:大循环遍历作为左数,小循环从下一个开始遍历作为右数,时间复杂度是O(n^2)。——竟然不让我通过%>_<%
2.哈希散列,用map<int, int>实现,序号(左值)是原序列中的值,保存的值(右值)是原序列的序号,每次从map中遍历。每次查找当前(target-当前值)是否已在表中,
若已存在,则返回key对应的序号和当前序号,否则添加当前值到表中。
3.别人的办法:用unordered_map类,思路和2一样。
——2、3的思路:遍历原序列的值,而不是原序列的索引,可以减少一个级的复杂度(n^2到n),hashtable中查找元素时间为常数的优势。
4.c的思路:先排序,然后用快排思想,一个在头一个在尾,比较头尾两数的和与指定值的大小。或者先快排至有序,然后二分查找。时间是O(nlogn).
【思路2+3 other code】注意:使用map要#include<map>
vector<int> twoSum(vector<int>& nums, int target) { vector<int> result(2); map<int,int> intMap;//思路2
//unordered_map<int,int> intMap;//思路3 for(int i=0; i<nums.size(); ++i){ if(intMap.find(target-nums[i]) != intMap.end()){ result[0] = intMap[target-nums[i]] + 1; result[1] = i + 1; return result; } intMap[nums[i]] = i; } }
【结果】
用思路3的unordered_map耗时20ms,排名居中;
用思路2的map耗时39ms,排名最后,可见散列表的效率要更高些,
因为map底层使用红黑树实现的,所以它的查找时间是O(logN),略逊于hash_map,但是这不是绝对的。
(see more:http://blog.csdn.net/jiadebin890724/article/details/23305449)
find()函数返回一个迭代器指向键值为key的元素,如果没找到就返回指向map尾部的迭代器。
这个“键值”就是指“序号”,如果直接引用intMap[key],key是一个未曾出现过的键,那么映射表会自动创建一个具有这个键的新元素,即intMap[nums[i]] = i;
【思路4】
vector<int> twoSum(vector<int>& nums, int target) { vector<int> result; int n=nums.size(); sort(nums.begin(), nums.end()); int i=0,j=n-1; while(i<j){ if(nums[i]+nums[j]==target){ result.push_back(i+1); result.push_back(j+1); return result; } else if(nums[i]+nums[j]<target){ i++; } else if(nums[i]+nums[j]>target){ j--; } } }
排序用stl提供的sort函数很好实现,但是修改了原来元素的顺序,返回的是排序后的序号,是不符合题意的。可以间接实现:
struct Node { int data; int num; }; bool comparision(Node n1, Node n2) { return n1.data<n2.data; } vector<int> twosum(vector<int> &nums, int integer) { int first, second; const int length=nums.size(); vector<Node> nodes(length); vector<int> re; for(int i=0; i<length; i++) { nodes[i].data=nums[i]; nodes[i].num=i; } sort(nodes.begin(), nodes.end(),comparision); for(int i=0,j=length-1; i!=j;) { int sum=nodes[i].data+nodes[j].data; if(sum==integer) { if(nodes[i].num<nodes[j].num){ re.push_back(nodes[i].num); re.push_back(nodes[j].num); } else{ re.push_back(nodes[j].num); re.push_back(nodes[i].num); } return re; } else if(sum<integer) i++; else j--; } }
利用自定义结构体,把序号和值捆绑。其实相当于map。
还有更优美的写法,见http://blog.csdn.net/sunbaigui/article/details/8981343