Leetcode(1)——两数之和
题目
给定一个整数数组 numsnumsnums 和一个整数目标值 targettargettarget,请你在该数组中找出 和为目标值 targettargettarget 的那 两个 整数,并返回它们的数组下标。
- 你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
- 你可以按任意顺序返回答案。
示例 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]
提示:
- 2 <= nums.length <= 104
- -109 <= nums[i] <= 109
- -109 <= target <= 109
- 只会存在一个有效答案
进阶:你可以想出一个时间复杂度小于 O(n2)O(n^2)O(n2) 的算法吗?
题解
关键:如何快速获取某一个值
方法一:暴力枚举
思路
最容易想到的方法是枚举数组中的每一个数 xxx,寻找数组中是否存在 target−xtarget - xtarget−x。
当我们使用遍历整个数组的方式寻找 target−xtarget - xtarget−x 时,需要注意到每一个位于 xxx 之前的元素都已经和 xxx 匹配过,因此不需要再进行匹配。而每一个元素不能被使用两次,所以我们只需要在 x 后面的元素中寻找 target−xtarget - xtarget−x。
代码实现
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
for(int i = 0; i < nums.size(); i++)
for(int j = i + 1; j < nums.size(); j++){
if(nums[i] + nums[j] == target)
return vector<int>{i, j};
}
return vector<int>();
};
复杂度分析
时间复杂度:O(N2)O(N^2)O(N2) ,其中 NNN 是数组 numsnumsnums 的长度,因为有两层 for 循环来遍历数组,外层 for 循环遍历数组的每个元素,内层 for 循环遍历数组来查找与它和为 targettargettarget 的数。
空间复杂度:O(1)O(1)O(1)
方法二:哈希表
思路
我们注意到方法一(暴力枚举)的时间复杂度较高的原因是寻找 target−xtarget - xtarget−x 的时间复杂度过高。因此,我们的 优化方向就是需要一种更优秀的方法,能够快速寻找数组中是否存在目标元素。如果存在,我们还需要找出它的索引。
我们可以很容易就想到使用哈希表,它可以将寻找 target−xtarget - xtarget−x 的时间复杂度降低到从 O(N)O(N)O(N) 降低到 O(1)O(1)O(1),还可以找出它的索引。
算法实现:
创建一个哈希表,遍历数组 numsnumsnums,对于数组中的每一个 xxx,我们首先查询哈希表中是否存在 target−xtarget - xtarget−x,然后将 xxx 插入到哈希表中,即可保证不会让 xxx 和自己匹配。
- 即一边将数组中的每个值插入哈希表中,一边检查哈希表中已存的值是否有要找的值(因为如果数组中存在两个加起来等于 targettargettarget 的值 A 和 B ,那么哪怕因为值 A 先入哈希表导致没有查找到另一个值 B,在另一个值 B 入哈希表时也一定可以查找到那个值 A),这样最多只需要遍历一遍数组即可得到结果。
- 而不是先将数组中的数字插入到哈希表中,在遍历数组并查找哈希表中是否存在要找的值,最多需要遍历两遍数组才能得到结果。
代码实现
我写的:
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
map<int,int> a;//建立hash表存放数组元素
vector<int> ans(2,-1);//存放结果
for(int i=0;i<nums.size();i++)
a.insert(map<int,int>::value_type(nums[i],i));
for(int i=0;i<nums.size();i++)
{
if(a.count(target-nums[i])>0&&(a[target-nums[i]]!=i))
//判断是否找到目标元素且目标元素不能是本身
{
ans[0]=i;
ans[1]=a[target-nums[i]];
break;
}
}
return ans;
}
};
优化后的:(提高一倍的速度)
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
unordered_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)O(N)O(N) ,其中 NNN 是数组中的元素数量。对于每一个元素 xxx,我们可以 O(1)O(1)O(1) 地寻找 target−xtarget - xtarget−x。
空间复杂度:O(N)O(N)O(N) ,其中 NNN 是数组中的元素数量,主要为哈希表的开销。
这篇博客介绍了LeetCode中经典的两数之和问题的解决方案,包括暴力枚举和哈希表两种方法。暴力枚举的时间复杂度为O(N^2),而哈希表的优化方案可以将时间复杂度降低到O(N)。通过建立哈希表,可以快速查找目标元素,避免了重复匹配,提高了效率。文章强调了哈希表在解决此类问题中的重要作用。
2819

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



