leetcode 18. 4Sum


  1. 4Sum:题目链接

2Sum 3Sum的基础上进行升级

解法1:双指针

基本思想: 用四个指针i,j,left,right分别指向排好序后,从左往右对应nums[i] + nums[j] + nums[left] + nums[right] == target;
用for循环遍历指针i,其有效范围[i,nums.length-4] 注意是左闭右闭区间,如果是左闭右开则是[i,nums.length-3)
用for循环遍历指针j,其有效范围[i+1, nums.length-3]
再用双指针方法在[j+1,nums.length-1]范围寻找left,right使得nums[i] + nums[j] + nums[left] + nums[right] == target

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class Solution1 {
// 时间复杂度O(n^3) 双指针
public List<List<Integer>> fourSum(int[] nums, int target) {
Arrays.sort(nums); // 按从小到大 排序 nums[i] <= nums[j] <= nums[left] <= nums[right]
List<List<Integer>> res = new ArrayList<>();
// 遍历第一个指针i 范围[0,nums.length-4]
for (int i = 0; i < nums.length - 3; ++i) {
if (nums[i] + nums[i + 1] + nums[i + 2] + nums[i + 3] > target) { // 如果四个最小的元素都比target大
break;
}
if (nums[i] + nums[nums.length - 1] + nums[nums.length - 2] + nums[nums.length - 3] < target) {
// nums[i]和三个最大元素的和都比target小 i++
continue;
}
// 选取第一个元素时 如果发现存在两个或以上的nums[i]相等,选取最后一个,防止在res中出现重复结果
if (i == 0 || (i > 0 && nums[i] != nums[i - 1])) {
// 遍历第二个指针j 范围[i+1, nums.length-3]
for (int j = i + 1; j < nums.length - 2; ++j) {
if (nums[i] + nums[j] + nums[j + 1] + nums[j + 2] > target) { // 说明第二个元素nums[j]太大
break;
}
if (nums[i] + nums[j] + nums[nums.length - 1] + nums[nums.length - 2] < target) {
// 说明nums[j] 太小 j++
continue;
}
// 在[i+1,nums.length-3]从如果出现连续nums[j]相等 取最后一个 预防在res中出现重复元素
if (j == i + 1 || (j > i + 1 && nums[j] != nums[j - 1])) {
// 使用双指针
int left = j + 1;
int right = nums.length - 1;
while (left < right) {
int sum = nums[i] + nums[j] + nums[left] + nums[right];
if (sum == target) {
// 取连续相等nums[left]中的最后一个
while (left < right && nums[left] == nums[left + 1]) {
left++;
}
// 取连续相等nums[right]中的从右往左的最后一个
while (left < right && nums[right] == nums[right - 1]) {
right--;
}
List<Integer> list = new ArrayList<>();
list.add(nums[i]);
list.add(nums[j]);
list.add(nums[left++]);
list.add(nums[right--]);
res.add(list);
} else if (sum > target) {
right--;
} else {
left++;
}
}
}
}
}
}
return res;
}

public static void main(String[] args) {
int[] nums = {-1, 0, 1, 2, -1, -4};
int target = -1;
List<List<Integer>> res = new Solution1().fourSum(nums, target);
System.out.println(res);
}
}

pS: 源代码链接

文章目录
  1. 1. 解法1:双指针
|