[LeetCode热题100]第一题 两数之和
题目描述
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出和为目标值 target 的那两个整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
示例 1:
输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
示例 2:
输入:nums = [3,2,4], target = 6
输出:[1,2]
示例 3:
输入:nums = [3,3], target = 6
输出:[0,1]
进阶:你可以想出一个时间复杂度小于 O(
n
2
n^2
n2) 的算法吗?
来源:LeetCode
链接:https://leetcode.cn/problems/two-sum/?envType=study-plan-v2&envId=top-100-liked
解法一 暴力匹配
思路:
从第一个元素开始,找寻该元素后是否有相加等于目标值(target)的元素,如果有则将这两个元素压入目标容器,没有则进入下一循环(i++)
代码
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
vector<int>res;
for(int i=0;i<nums.size();i++)
{
for(int j=i+1;j<nums.size();j++)
{
if(nums[i]+nums[j]==target)
{
res.push_back(i);
res.push_back(j);
}
}
}
return res;
}
};
提交结果
复杂度分析
时间复杂度:O(
N
2
N^2
N2),,其中 N是数组中的元素数量。最坏情况下数组中任意两个数都要被匹配一次。
空间复杂度:O(1)
作者:力扣官方题解
链接:https://leetcode.cn/problems/two-sum/
来源:力扣(LeetCode)
解法二 哈希表
思路
求两数之和,联想到用哈希表中的find来找是否存在两数和等于目标值的元素。具体来说,首先创建一个空的哈希表,遍历vector容器,遍历过程中,通过find函数寻找是否存在两数之和等于目标值,若存在,则将这两个数的下标返回,如若没有,则将该数存入map容器中作为潜在两数和元素
代码
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
//运用哈希表的find来查找是否有符合要求的元素
//注意find找的是key即键值所以要把数组的值给key,索引给value
map<int,int>hashtable;
for(int i=0;i<nums.size();i++)
{
auto it = hashtable.find(target-nums[i]);
if(it!=hashtable.end())
{
//说明已找到匹配
return {it->second,i};
}
//由于题目已表明同一个元素在答案中不会重复出现
//所以即便有相同元素做键值也没关系
//特别地,如果两个相同元素一起做键值,后者会覆盖掉前者的记录
hashtable[nums[i]]=i;
}
return {};
}
};
提交结果
复杂度分析
时间复杂度:O(N),其中 N 是数组中的元素数量。对于每一个元素 x,我们可以 O(1) 地寻找 target - x。
空间复杂度:O(N),其中 N 是数组中的元素数量。主要为哈希表的开销。
作者:力扣官方题解
链接:https://leetcode.cn/problems/two-sum/
来源:力扣(LeetCode)
解法三 先排序再移动两端标识寻找两数和
思路
受吴师兄学算法公众号文章的启发,先对vector容器中的元素进行排序,注意为避免原vector容器下标错乱,这里将原容器中的元素拷贝到copy中,对经排序后的copy容器,给定i,j两个迭代器做标识用于移动,分别赋予初值容器开始,容器结束
在i<j的循环下,计算*i+*j,若等于目标值,则返回下标,break跳出循环,这里找元素用到了find()函数但是find返回的是第一个找到的元素,若有重复元素之和为目标值则失效,所以做了逻辑判断,不等直接find,相等则通过for找到另一个
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
vector<int>copy = nums;
vector<int>res;
sort(copy.begin(),copy.end());//STL语法默认从小到大排序
//给予两个标识,一个在vector容器开始,一个在vec容器结束
vector<int>::iterator i=copy.begin();
vector<int>::iterator j=copy.end()-1;
int num=0;
while(i<j)
{
num=*i+*j;
if(num==target)
{
vector<int>::iterator m,n;
if(*i!=*j)
{
m=find(nums.begin(),nums.end(),*i);
n=find(nums.begin(),nums.end(),*j);
res.push_back(distance(nums.begin(),m));
res.push_back(distance(nums.begin(),n));
}
else
{
for(vector<int>::iterator it=nums.begin();it!=nums.end();it++)
{
if(*it==*i)
res.push_back(distance(nums.begin(),it));
}
}
break;
}
else if(num<target)
{
i++;
}
else if(num>target)
{
j--;
}
}
return res;
}
};
提交结果