小硕即将面临找工作的压力,没事编编Leetcode。分享一些经验大家。
刚开始,博主低估了LeetCode的要求,采用了一个最直观偷懒的方法。两层循环遍历,时间复杂度O(N^2)。LeetCode返回结果Time Limited Exceeded。贴出挫代码引以为戒。
class Solution {
public:
vector<int> twoSum(vector<int> &numbers, int target) {
vector<int> ::iterator iteFirst = numbers.begin();
vector<int>::iterator iteSecond;
int index1, index2;
vector<int> vecRel;
for(index1=1; iteFirst != numbers.end(); iteFirst++, index1++)
{
int n = target- *iteFirst;
for(index2 = index1+1, iteSecond = iteFirst + 1; iteSecond != numbers.end(); iteSecond++, index2++)
{
if(*iteSecond == n)
{
vecRel.push_back(index1);
vecRel.push_back(index2);
return vecRel;
}
}
}
}
};
此题的归根到底是查找的优化问题。当target和当前元素已定,只要查找(target-当前元素)是否在序列中即可。我们可以进行快排然后折半查找,时间复杂度为O(N*logN)。但是不要忘了STL中的模板map,调用简单,并且查找的时间复杂度也是O(log(N))。因此,思路为遍历numbers序列,将其存在map中,其中key值为number的值,value为number出现的顺序,查找(target-当前元素)是否在map中即可,时间复杂度O(N*log(N)).代码如下:
class Solution {
public:
vector<int> twoSum(vector<int> &numbers, int target) {
map<int, int> mapNum;
vector<int> ::iterator iteFirst = numbers.begin();
for(int i = 1; iteFirst != numbers.end(); iteFirst++, i++)
mapNum[*iteFirst] = i;
int index1;
vector<int> vecRel;
for(index1=1, iteFirst = numbers.begin(); iteFirst != numbers.end(); iteFirst++, index1++)
{
int n = target- *iteFirst;
if(mapNum.find(n) != mapNum.end())
{
if(mapNum[n] == index1)
continue;
else{
vecRel.push_back(index1);
vecRel.push_back(mapNum[n] );
return vecRel;
}
}
}
}
};
博主在第一次本算法时,未加判断条件map(Num[n]) == index1,测试用例[3,2,4],6没过,我返回的值是[1,1],正确答案是[2,3]。原因就是没有判断两次取到的数是不是都一个,希望大家也多多注意,别掉进坑里。还有大牛用O(N)的时间复杂度实现,具体做法是将数据存在hashmap里,这样查询的时间就是O(1)级别,因为C++模板库里没有hashmap的实现,所以小硕就偷偷懒,直接调STL中的map了。算法时间复杂度截图如下,有图可见C++的时间效率还是比较高的。