1. 问题描述:
给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那两个整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。
示例:
给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/two-sum
2. 思路分析:
① 题目不难理解,在一开始的时候想到使用递归来求解,在递归的方法中使用两个指针一个是左边的指针,一个是右边的指针,我们在计算的时候可以有两种可能的操作,一种是左边的指针移动一位,右边的指针不动,另外一种是左边的指针不动,右边的指针向左移动一位所以对应着两种平行的状态,所以使用两种方法进行递归即可,并且在递归的时候使用一个二维数组来记录求解过的结果,当在递归的时候发现之前求解过了那么就直接返回了,但是在提交的时候超出内存限制了,可能是数据量太大了,所以使用了另外一种方法来解决
② 由于使用递归超时了,所以使用了map来进行映射,在一开始的时候遍历整个数组,将数组中对应的值与值对应的下表进行映射,并且值为Deque类型可以避免题目种两个数组元素是一样的情况,使用map进行数组值与下标的映射主要是为了在之后排序之后还能够找到排序之前数字对应的下标值,我们使用map进行映射之后,对数组进行排序,在循环中使用左右指针来操作,假如太小了左指针往右移,太大了右指针往左移直到两个元素相等,这样就可以避免递归超时的问题了
③ 在官方的题解中它是结合了题目中最多出现两个数字相同的情况,所以使用一次for循环遍历结合哈希表进行解决,在求解的时候使用了相减的情况来找到另外一个数字的映射情况,从解决了重复数字的映问题以及查询的效率问题,写的代码非常棒
3. 代码如下:
我自己写的代码:
class Solution {
public int[] twoSum(int[] nums, int target) {
int res[] = new int[2];
Map<Integer, Deque<Integer>> map = new HashMap<>();
/*使用map来进行记录*/
for (int i = 0; i < nums.length; ++i){
map.put(nums[i], map.getOrDefault(nums[i], new ArrayDeque()));
map.get(nums[i]).add(i);
}
Arrays.sort(nums);
/*使用快慢指针来解决*/
int l = 0, r = nums.length - 1;
while (l < r){
if (nums[l] + nums[r] == target){
res[0] = map.get(nums[l]).pop();
res[1] = map.get(nums[r]).pop();
return res;
}else if (nums[l] + nums[r] < target) ++l;
else --r;
}
return null;
}
}
class Solution {
int res[] = new int[2];
int rec[][];
public int[] twoSum(int[] nums, int target) {
rec = new int[nums.length][nums.length];
recursion(nums, target, 0, nums.length - 1);
return res;
}
/*使用一个数组来记录中间的求解过程*/
private void recursion(int[] nums, int target, int l, int r) {
if (l >= r) return;
if (rec[l][r] == -1) return;
if (nums[l] + nums[r] == target){
res[0] = l;
res[1] = r;
return;
}
/*存在两个平行的状态: l加r不变, l不变r减*/
recursion(nums, target, l + 1, r);
recursion(nums, target, l, r - 1);
rec[l][r] = -1;
}
}
官方代码:
class Solution {
public int[] twoSum(int[] nums, int target) {
Map<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
int complement = target - nums[i];
if (map.containsKey(complement)) {
return new int[] { map.get(complement), i };
}
map.put(nums[i], i);
}
throw new IllegalArgumentException("No two sum solution");
}
}