题目:
给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。
示例:
给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]
题解:
解法一:暴力法
用双重循环遍历向量,如果对应元素和等于target,则输出下标{i,j},否则输出空。
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
for (int i = 0; i < nums.size()-1; i++)
{
for (int j = i+1; j < nums.size(); j++)
{
if (nums[i]+nums[j]==target)
{
return {i,j};
}
}
}
return {};
};
};
-
nums.size()获取向量元素个数
-
第一次遍历终点是倒数第二个元素而不是向量尾
-
对于每一个元素,要遍历数组的其余部分来寻找目标元素,耗费时间是O(n),则总的时间复杂度是O(n2)
-
空间复杂度是O(1)
解法二:两遍哈希表
暴力法虽然思路简单,但是时间复杂度偏大,有进一步优化的空间。
此题的关键是为每一个元素查找符合条件的目标元素,如果找到,则获取并输出索引。
而保持数组中每个元素和索引相互对应的最好方法便是哈希表。
我们使用两次迭代:第一次迭代构建元素-下标的哈希表;第二次迭代检查每个元素的目标元素(target - nums[i])是否存在于表中,要注意两次取值不能相同,目标元素不能是 nums[i] 本身。
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
unordered_map<int, int> indices;
//第一次遍历 建立map
for (int i = 0; i < nums.size(); i++)
{
indices[nums[i]]=i;
}
//第二次遍历 查找目标元素
for (int i = 0; i < nums.size(); i++)
{
if (indices.find(target-nums[i])!=indices.end()&&i!=indices[target-nums[i]])
{
return {i,indices[target-nums[i]]};
}
}
return {};
};
};
- indices.find() 返回被查找元素的位置,没有则返回map.end()
- 哈希表将查找时间复杂度降低到O(1),总时间复杂度是O(n)
- 哈希表中储存了n个元素,空间复杂度是O(n)
解法三:一遍哈希表
改进方法二,将构建哈希表和查找目标元素合并在一起。
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()&&i!=indices[target-nums[i]])
{
return {i,indices[target-nums[i]]};
}
indices[nums[i]]=i;
}
return {};
};
};
解法四:双指针遍历
将数据排序后存入新的数组,用头指针和尾指针从数组两边向中间查找,直到找到目标元素。
//存储数字的结构体
struct Num
{
int value;
int index;
};
//比较函数
bool cmp(const Num &n1, const Num &n2)
{
return n1.value < n2.value;
}
class Solution
{
public:
vector<int> twoSum(vector<int> &nums, int target)
{
int size = nums.size();
int top = 0;
int tail = size - 1;
//构建新的排序数组
Num num[size];
for (int i = 0; i < size; i++)
{
num[i].value = nums[i];
num[i].index = i;
}
stable_sort(num, num + size, cmp);
//双指针查找
while (top < tail)
{
if (num[top].value + num[tail].value == target)
{
return {num[top].index, num[tail].index};
}
else if (num[top].value + num[tail].value < target)
{
top++;
}
else
{
tail--;
}
}
return {};
};
};
- stable_sort():可以保证相等的元素在排序后次序不变。
本文深入探讨了经典的两数之和问题,提供了四种高效解决方案,包括暴力法、两遍哈希表、一遍哈希表及双指针遍历。通过对比不同算法的时间与空间复杂度,帮助读者理解各种方法的优缺点。
1855

被折叠的 条评论
为什么被折叠?



