给定一个整数数组 nums
和一个整数目标值 target
,请你在该数组中找出 和为目标值 target
的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
这一题,是我见过LeetCode里最简单的一题,虽然被归类到了哈希表中,但是暴力枚举永远是简单粗暴的:
class Solution {
public:
std::vector<int> twoSum(std::vector<int>& nums, int target)
{
std::vector<int> ret; //定义返回的vector
int S = nums.size(); //确定目标数组大小好确定范围
for (int i = 0; i < S-1; i++) //for循环嵌套,冒泡排序般遍历每一个元素组合,同时为了避免重复将外部for循环遍历到倒数第二个元素
{
for (int j = i + 1; j < S; j++)//内部循环为外部循环的下一个到最后一个,有效防止内外同时指定到一个元素
{
if (nums[i] + nums[j] == target)//如果满足条件则将之推入返回vector
{
ret.push_back(i);
ret.push_back(j);
}
}
}
return ret;
}
};
但是很显然这里的时间复杂度是o(),很明显就不够节省,有明显的优化空间嘛,那可不可以有别的思路来完成任务呢?很显然可以用哈希表来解决,哈希表中有一个方法叫做.find()
HashName.find()
括号内填需要查找的哈希表值,如果找到,返回该指向键值对的迭代器,具体取键或值分别用如下方法查找,如果没找到,返回该哈希表的末尾;就有了以下方法:
iter->first;取键
iter->second;取值
class Solution {
public:
std::vector<int> twoSum(std::vector<int>& nums, int target)
{
std::unordered_map<int, int> hs;//定义哈希表,键值的类型都为int,键代表了nums每个元素的值,值则代表了在Nums中的位置
int S = nums.size(); //简便定义vector长度
for (int i = 0; i < S; i++)//遍历nums
{
auto iter = hs.find(target - nums[i]);//从已有的哈希表中寻找是否有于当前配对的值
if (iter != hs.end())//找到了匹配的
{
return { i,iter->second };那么返回这两个数字的定位
}
else
hs[nums[i]] = i;//如果没找到,那么将此个nums中的值和索引存入哈希表
}
}
};
可能的问题:如何避免重复问题?
答:我们将nums和hs理解为两个不同的空间,每次对应的nums[i]在hs中一定不会存储。
比如:nums={3,4,1,2},target=6;
1. hs为空,此时i=0;nums[i]=3;遍历hs没有与之配对的,将nums[i]和i存入hs,以{3(nums[0]的值),0(索引,位置)}存储在hs中
2. hs={{3,0}} i=1 nums[i]=4;遍历同样没有与之配对,将{4,1}存入hs
3. hs={{3,0} {4,1}} i=2 nums[i]=1;遍历hs,没有找到与1能配对为6的,将{1,2}存入hs
4. hs={{3,0}{4,1}{1,2}} i=3 nums[i]=2;遍历hs,发现其中的4和nums[i]=2可以配对为6,两个数的索引输出。
所以可以看到这样是绝对不会重复利用同一个元素的。