Skip to content

Commit be6623d

Browse files
author
wangpeng
committed
feat(MEDIUM): _18_fourSum
1 parent 1ea0b0e commit be6623d

File tree

1 file changed

+142
-0
lines changed

1 file changed

+142
-0
lines changed
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
package pp.arithmetic.leetcode;
2+
3+
import pp.arithmetic.Util;
4+
5+
import java.util.ArrayList;
6+
import java.util.Arrays;
7+
import java.util.List;
8+
9+
/**
10+
* Created by wangpeng on 2019-04-10.
11+
* 18. 四数之和
12+
* <p>
13+
* 给定一个包含 n 个整数的数组 nums 和一个目标值 target,判断 nums 中是否存在四个元素 a,b,c 和 d ,使得 a + b + c + d 的值与 target 相等?找出所有满足条件且不重复的四元组。
14+
* <p>
15+
* 注意:
16+
* <p>
17+
* 答案中不可以包含重复的四元组。
18+
* <p>
19+
* 示例:
20+
* <p>
21+
* 给定数组 nums = [1, 0, -1, 0, -2, 2],和 target = 0。
22+
* <p>
23+
* 满足要求的四元组集合为:
24+
* [
25+
* [-1, 0, 0, 1],
26+
* [-2, -1, 1, 2],
27+
* [-2, 0, 0, 2]
28+
* ]
29+
*
30+
* @see <a href="https://leetcode-cn.com/problems/4sum/">4sum</a>
31+
*/
32+
public class _18_fourSum {
33+
34+
public static void main(String[] args) {
35+
_18_fourSum fourSum = new _18_fourSum();
36+
List<List<Integer>> lists = fourSum.fourSum(new int[]{-3, -2, -1, 0, 0, 1, 2, 3}, 0);
37+
for (int i = 0; i < lists.size(); i++) {
38+
Util.printList(lists.get(i));
39+
}
40+
}
41+
42+
/**
43+
* 解题思路:
44+
* 1、先对数组进行排序
45+
* 2、先用四个指针i1=0,i2=1,i3=len-2,i4=len-1,分别指向数组开头和结尾两处
46+
* 3、先控制i1,i4不动,i2,i3向中心遍历,寻找满足条件的所有情况
47+
* 4、i1,i4再想内部移动,重复步骤#3
48+
* 5、注意遍历过程总重复数据的问题
49+
* <p>
50+
* 首次提交:
51+
* 执行用时 : 77 ms, 在4Sum的Java提交中击败了64.43% 的用户
52+
* 内存消耗 : 39.5 MB, 在4Sum的Java提交中击败了13.83% 的用户
53+
* 时间复杂度在O(n^3)级别,待优化
54+
* 优化方案:添加一些异常情况,提前终止遍历
55+
* 优化提交:
56+
* 执行用时 : 26 ms, 在4Sum的Java提交中击败了96.13% 的用户
57+
* 内存消耗 : 39.7 MB, 在4Sum的Java提交中击败了13.83% 的用户
58+
*
59+
* @param nums
60+
* @param target
61+
* @return
62+
*/
63+
public List<List<Integer>> fourSum(int[] nums, int target) {
64+
List<List<Integer>> retList = new ArrayList<>();
65+
int length = nums.length;
66+
if (length < 4) {
67+
return retList;
68+
}
69+
//先排序
70+
Arrays.sort(nums);
71+
//定义四个指针
72+
int i1 = 0, i4 = length - 1;
73+
int i2, i3;
74+
while (i1 < length - 2) {
75+
//添加终止条件
76+
if (nums[i1] * 4 > target) {
77+
break;
78+
}
79+
if (i1 >= i4 - 2 || nums[i1] + nums[i4] * 3 < target) {
80+
i1 = getNextIndex(nums, i1);
81+
i4 = length - 1;
82+
continue;
83+
}
84+
i2 = i1 + 1;
85+
i3 = i4 - 1;
86+
while (i2 < i3) {
87+
int sum = nums[i1] + nums[i2] + nums[i3] + nums[i4];
88+
if (sum == target) {
89+
retList.add(Arrays.asList(nums[i1], nums[i2], nums[i3], nums[i4]));
90+
i2 = getNextIndex(nums, i2);
91+
i3 = getPreIndex(nums, i3);
92+
continue;
93+
}
94+
if (sum > target) {
95+
i3 = getPreIndex(nums, i3);
96+
continue;
97+
}
98+
if (sum < target) {
99+
i2 = getNextIndex(nums, i2);
100+
continue;
101+
}
102+
}
103+
i4 = getPreIndex(nums, i4);
104+
}
105+
106+
return retList;
107+
}
108+
109+
/**
110+
* 获取下个不重复index
111+
*
112+
* @param nums
113+
* @param ci
114+
* @return
115+
*/
116+
private int getNextIndex(int[] nums, int ci) {
117+
int c = nums[ci];
118+
for (int i = ci + 1; i < nums.length; i++) {
119+
if (nums[i] != c) {
120+
return i;
121+
}
122+
}
123+
return nums.length - 1;
124+
}
125+
126+
/**
127+
* 取前一个不重复的index
128+
*
129+
* @param nums
130+
* @param ci
131+
* @return
132+
*/
133+
private int getPreIndex(int[] nums, int ci) {
134+
int c = nums[ci];
135+
for (int i = ci - 1; i >= 0; i--) {
136+
if (nums[i] != c) {
137+
return i;
138+
}
139+
}
140+
return 0;
141+
}
142+
}

0 commit comments

Comments
 (0)