1.两数之和
给定一个整数数组 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]
提示:
- 2 ≤ n u m s . l e n g t h ≤ 1 0 4 2 \leq nums.length \leq 10^4 2≤nums.length≤104
- − 1 0 9 ≤ n u m s [ i ] ≤ 1 0 9 -10^9 \leq nums[i] \leq 10^9 −109≤nums[i]≤109
- − 1 0 9 ≤ t a r g e t ≤ 1 0 9 -10^9 \leq target \leq 10^9 −109≤target≤109
- 只会存在一个有效答案
解题
- 首先我们可以先将数组元素存储到哈希表中
- 然后对数组进行遍历
- 每遍历一个元素,就查询哈希表中是否具有对应的值num,使
num+nums[i] = target
成立 - 且查询到的值的索引不能与当前遍历的数组元素的索引相同
- 若满足条件则退出循环,并返回结果
具体代码实现如下:
class Solution {public int[] twoSum(int[] nums, int target) {// 创建哈希表存储数组元素HashMap<Integer, Integer> numHash = new HashMap<>();int n = nums.length; // 记录数组长度int i = 0;int j = 0;// 将数组元素存储到哈希表中for (i = 0; i < n; ++i) {numHash.put(nums[i], i);}// 通过遍历数组元素,并查询哈希表找出对应的另一个整数for (i = 0; i < n; ++i) {int num = target - nums[i];if (numHash.containsKey(num) && numHash.get(num) != i) {j = numHash.get(num);break;}}return new int[]{i, j};}
}
提交结果如下所示:
解答成功:
执行耗时:4 ms,击败了53.42% 的Java用户
内存消耗:43 MB,击败了5.00% 的Java用户
进一步优化,思路如下:
- 首先关于如何查询 数组中存在的另一个满足条件的元素
target-num[i]
时间复杂度为O(1),无法再进行优化 - 通过与官方题解对比,主要耗费时间在于第一次遍历数组将数组元素存储到哈希表需要耗费不少时间
- 可以尝试将第一次遍历数组和第二次遍历数组结合起来
代码实现如下:
class Solution {public int[] twoSum(int[] nums, int target) {HashMap<Integer, Integer> numHash = new HashMap<>();int n = nums.length;for (int i = 0; i < n; ++i) {int num = target - nums[i];if (numHash.containsKey(num)) {return new int[]{i, numHash.get(num)};} else {numHash.put(nums[i], i);}}return new int[]{0};}
}
我们对于每一个nums[i]
先查询表中是否存在target - nums[i]
:
- 若不存在,则说明对应的
target - nums[i]
要么不在数组中;要么在数组中,只是还未插入哈希表中,因此可将该元素插入到哈希表中,在后续遍历到值为target - nums[i]
的数组元素时,即可获得最终结果。 - 若存在,则说明已经找到满足条件的答案,直接将查找结果返回即可
使用如上方法,不但减少时间复杂度以及对空间的损耗,还可以避免查询到的target - nums[i]
与自身nums[i]
匹配。
提交结果如下所示:
解答成功:
执行耗时:1 ms,击败了99.55% 的Java用户
内存消耗:42.5 MB,击败了63.87% 的Java用户