【题目描述】 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。 题目来源:力扣(LeetCode) |
【示例输出】 给定 nums = [2, 7, 11, 15], target = 9 因为 nums[0] + nums[1] = 2 + 7 = 9 |
解法一:暴力遍历
最直观的想法,从第一个元素开始遍历,分别将当前元素与剩下的元素相加,如果等于目标值则输出他们的下标,代码如下:
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target);
};
vector<int> Solution::twoSum(vector<int>& nums, int target)
{
vector<int> indexs(2,-1);//初始化结果容器
for(int i=0;i<nums.size();i++)
{
for(int j=i+1;j<nums.size();j++)
{
if(nums[i]+nums[j]==target)
{
indexs.clear();//清理容器,输入元素下标
indexs.push_back(i);
indexs.push_back(j);
return indexs;
}
}
}
return indexs;
}
复杂度分析:
时间复杂度:暴力破解的循环极限次数为,因此时间复杂度需要
,有待优化
空间复杂度:只需要存两个最终目标值的下标,因此空间复杂度为
解法二:哈希映射
问题最终归结为:给出一个数及其下标,找到其补数的下标,这边的补数我们定义为目标值与当前值的差。显而易见,为了遍历给出的所有数,必须存在一个最外层循环,这个循环得花费的复杂度,使得复杂度指数增长的部分在第二层循环——为了找到与之匹配的补数,花费的成本太大了。因此我们会想,如果遍历到某个数时能够直接知道数组中是否存在该数的补数就好了,这样就能够将时间复杂度降为
,为了将查找时间控制在
,我们很容易想到哈希映射——将每个数与其索引对应起来的同时将该数的补数与其索引对应起来,通过空间换时间的方法,把查找时间复杂度降为
,具体代码如下:
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target);
};
vector<int> Solution::twoSum(vector<int>& nums, int target)
{
vector<int> indexs(2,-1);
map<int,int> hashmap;
for(int i = 0; i < nums.size(); i++)
{
if(hashmap.count(target-nums[i]) > 0)//如果补数存在
{
indexs.clear();
indexs.push_back(hashmap[target-nums[i]]);//存入补数对应的下标
indexs.push_back(i);//存入当前数对应的下标
return indexs;
}
hashmap[nums[i]] = i;//将数值作为键,下标作为数值存入map
}
return indexs;
}
复杂度分析:
时间复杂度:最外层遍历用了,哈希查找用了
,总的时间复杂度为
空间复杂度:最坏情况下,给定数组的第一个数的补数为数组中最后一个数,此时空间复杂度为