-
Notifications
You must be signed in to change notification settings - Fork 50
/
Copy path3 Sum.java
139 lines (116 loc) · 4.69 KB
/
3 Sum.java
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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
思路:
首先第一种解法,也是最暴力的解法: DFS O(2^N)
先对numbers进行排序(为了去重),然后使用DFS对该数组的subset进行遍历,
然后将符合条件的添加到results中,但是该方法时间复杂度过高(2^n),
故我们需要考虑更优解。
第二种解法: Two Pointers O(N^2)
依旧相对numbers进行排序(去重所需),然后使用头尾两个指针从数组头尾分别
向中间移动。寻找两个数nums[left], nums[rigth].使其加上原来保存的target值为0
这样我们便得到了一组解。
实质上是将该问题转换为 2Sum 的问题来解决。找出一个数,然后在后面的部分中找到
两个和为 Target - num[i] 的数 (2Sum)。该题中 Target 为 0.即找到两个数和为 -num[i] 的即可。
/*
Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0?
Find all unique triplets in the array which gives the sum of zero.
Example
For example, given array S = {-1 0 1 2 -1 -4}, A solution set is:
(-1, 0, 1)
(-1, -1, 2)
Note
Elements in a triplet (a,b,c) must be in non-descending order. (ie, a ≤ b ≤ c)
The solution set must not contain duplicate triplets.
Tags Expand
Two Pointers Sort Array Facebook
*/
// Version 1: Recursive Search DFS
public class Solution {
/**
* @param numbers : Give an array numbers of n integer
* @return : Find all unique triplets in the array which gives the sum of zero.
*/
public ArrayList<ArrayList<Integer>> threeSum(int[] numbers) {
// write your code here
ArrayList<ArrayList<Integer>> results = new ArrayList<>();
if (numbers == null) {
return results;
}
Arrays.sort(numbers);
helper(results, new ArrayList<Integer>(), 0, 0, numbers);
return results;
}
private void helper(ArrayList<ArrayList<Integer>> results,
ArrayList<Integer> list,
int startIndex,
int target,
int[] numbers) {
if (list.size() == 3 && target == 0) {
results.add(new ArrayList<Integer>(list));
return;
}
for (int i = startIndex; i < numbers.length; i++) {
if (target > 0) {
break;
}
if (i > 0 && i != startIndex && numbers[i - 1] == numbers[i]) {
continue;
}
list.add(numbers[i]);
helper(results, list, i + 1, target + numbers[i], numbers);
list.remove(list.size() - 1);
}
}
}
// Version 2: Two Pointers
// Change it into 2Sum
public class Solution {
/**
* @param nums : Give an array numbers of n integer
* @return : Find all unique triplets in the array which gives the sum of zero.
*/
public ArrayList<ArrayList<Integer>> threeSum(int[] nums) {
ArrayList<ArrayList<Integer>> results = new ArrayList<>();
if (nums == null || nums.length < 3) {
return results;
}
Arrays.sort(nums);
for (int i = 0; i < nums.length - 2; i++) {
// skip duplicate triples with the same first numebr
if (i > 0 && nums[i] == nums[i - 1]) {
continue;
}
int left = i + 1, right = nums.length - 1;
int target = -nums[i];
twoSum(nums, left, right, target, results);
}
return results;
}
public void twoSum(int[] nums,
int left,
int right,
int target,
ArrayList<ArrayList<Integer>> results) {
while (left < right) {
if (nums[left] + nums[right] == target) {
ArrayList<Integer> triple = new ArrayList<>();
triple.add(-target);
triple.add(nums[left]);
triple.add(nums[right]);
results.add(triple);
left++;
right--;
// skip duplicate pairs with the same left
while (left < right && nums[left] == nums[left - 1]) {
left++;
}
// skip duplicate pairs with the same right
while (left < right && nums[right] == nums[right + 1]) {
right--;
}
} else if (nums[left] + nums[right] < target) {
left++;
} else {
right--;
}
}
}
}