题目描述:给出一个目标数值target,求出数组中是否有两个元素的和等于target,如果有将下标输出出来
我的第一想法是暴力运算:
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target)
{
vector<int> vec;
for(int i=0;i!=nums.size();i++)
{
for(int j=i+1;j!=nums.size();j++)
{
int sum=nums[i]+nums[j];
if(sum==target)
{
vec.push_back(i);
vec.push_back(j);
}
}
}
return vec;
}
};
暴力计算的时间复杂度是n的平方量级,由于不用申请新的空间,空间复杂度为O(1)
运行情况:
- runtime:360ms
- memory usage:9.1MB
第二种想法调用了库函数,时间复杂度降到了nlogn量级
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target)
{
int i,j=0;
for(i=0;i!=nums.size();i++)
{
int sup=target-nums[i];
auto it=find(nums.begin()+i+1,nums.end(),sup);
if(it!=nums.end())
{
j=it-nums.begin();
break;
}
}
return vector<int>{i,j};
}
};
运行情况:
- runtime:108ms
- memory usage:9.1MB
第二种情况似乎更好,然后翻看答案,官方解法:One Pass Hash Table
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target)
{
unordered_map<int, int> indices;
for (int i = 0; i < nums.size(); i++)
{
if (indices.find(target - nums[i]) != indices.end())
{
return {indices[target - nums[i]], i};
}
indices[nums[i]] = i;
}
return {};
}
};
用到了关联容器map,map的first将nums[i]作为key,second保存相应的i,One Pass方法通过先查找的方式,如果map中没有另一个值,那么将当前nums[i]放入map中进行下一次查找,这种方式将用还没有放入map的nums[i]作为减数,在已放入map的值中查找差值,可以只遍历一次map,因为map的查找复杂度为O(1),所以该算法的时间复杂度为O(n);
PS:还有一种Two Pass算法,先把数组中的值都放入map再查找,也是O(n)。
查找复杂度为O(1)参考https://mp.csdn.net/mdeditor/89343430
运行情况:
- run time:16ms
- memory usage:10.1MB
总结:
- 利用其它算法(库函数的查找排序)提高效率
- 利用数据结构(map),牺牲空间换取时间,来提高效率