本文主要讲解使用哈希表解决两数之和的要点与细节,按照步骤一步步思考方便理解:
给定一个整数数组
nums
和一个整数目标值target
,请你在该数组中找出 和为目标值target
的那 两个 整数,并返回它们的数组下标。你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
c++与java代码如下,末尾
具体要点:
1. 大家刚开始做leecode第一题,如果没有经历算法题的训练,首先想到的一定是:两轮for循环,进行暴力匹配,但是这样子就失去了我们学习和做题的目的,如果所有题都暴力枚举,那么做题也就没了意义。并且暴力枚举的时间复杂度是O(N^2)
2. 我们首先分析一下这个题的核心点:
- 返回的是元素下标,而不是元素值
- nums[i]在nums中,target-nums[i]的值一定也在nums中
3. 通过2我们得出一个特性:需要判断一个元素是否出现过,即target-nums[i]是否曾经出现过
4. 既然要使用哈希表,那么我们选定使用set、map、数组,使用哪一种?
因为本题不仅涉及元素值,还涉及元素下标。所以map更适合我们的需求
5. 既然选定了map,那么我们思考一下map的含义
- map是用来存放我们遍历过的元素
- 其中key是元素值
- val是元素的下标
6. 把准备工作都做好,就可以开始遍历了,我们考虑一下遍历中的操作
- 首先获取 temp = target - nums[i];
- 判断temp是否出现过
- 如果出现过,那么nums[i]和temp对应的下标就是我们要的结果
- 如果没有出现过,那么把nums[i]和i存入map, 存放我们遍历过的元素
- 最后记得返回i,也就是哈希表的val,即下标
c++代码如下
class Solution {
public:
std::vector<int> twoSum(std::vector<int>& nums, int target) {
//定义返回的vector
vector<int> result;
//定义哈希表,key存元素,val存下标(因为最后返回结果是下标)
unordered_map<int, int> hashmap;
for (int i = 0;i < nums.size();i++) {
int temp = target - nums[i];
if (hashmap.find(temp) != hashmap.end()) {
result.push_back(i);
result.push_back(hashmap[temp]);
return result;
}
else hashmap.insert(pair<int, int>(nums[i], i));
}
//返回结果
return result;
}
};
java代码如下
class Solution {
public int[] twoSum(int[] nums, int target) {
int[] result = new int[2]; //初始化为0,0
//为什么要用map,因为不仅要知道 元素数值key,还要知道 元素下标val
//map用来存放我们遍历过的元素
Map<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
int temp = target - nums[i];
if (map.containsKey(temp)) {
result[0] = i; //下标val存入
result[1] = map.get(temp); //获取temp(key)的下标(val)
return result;
} else map.put(nums[i], i); //把遍历的元素加入哈希表
}
return result;
}