-
Notifications
You must be signed in to change notification settings - Fork 229
/
Copy path18-4sum.js
126 lines (116 loc) · 3.03 KB
/
18-4sum.js
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
/**
* @param {number[]} nums
* @param {number} target
* @return {number[][]}
*/
const fourSum = function (nums, target) {
nums.sort((a, b) => a - b)
const results = []
kSum(nums, target, 4, 0, [], results)
return results
}
function kSum(nums, target, k, i, acc, results) {
if (nums[i] * k > target || nums[nums.length - 1] * k < target) return
if (k > 2) {
for (let j = i; j <= nums.length - k; j++) {
if (j == i || nums[j] > nums[j - 1])
kSum(nums, target - nums[j], k - 1, j + 1, [...acc, nums[j]], results)
}
} else {
twoSum(nums, target, i, acc, results)
}
}
function twoSum(nums, target, i, acc, results) {
let lo = i
let hi = nums.length - 1
while (lo < hi) {
const sum = nums[lo] + nums[hi]
if (sum == target) {
results.push([...acc, nums[lo], nums[hi]])
while (nums[lo] == nums[lo + 1]) lo++
while (nums[hi] == nums[hi - 1]) hi--
lo++
hi--
} else if (sum < target) {
lo++
} else {
hi--
}
}
}
// another
/**
* @param {number[]} nums
* @param {number} target
* @return {number[][]}
*/
const fourSum = function(nums, target) {
return nSum(nums.sort((a, b) => a - b), target, 4, 0);
};
function nSum(nums, target, k, start) {
const res = [];
if (nums.length < k || k < 2 || target < nums[0] * k || target > nums[-1] * k)
return res;
if (k == 2) {
// 2 sum; ( improved to O(n) )
let r = nums.length - 1;
let l = start;
while (l < r) {
if (nums[l] + nums[r] === target) {
res.push([nums[l], nums[r]]);
//skip duplication
while (l < r && nums[l] === nums[l + 1]) l++;
while (l < r && nums[r] === nums[r - 1]) r--;
l++;
r--;
} else if (nums[l] + nums[r] < target) {
l++;
} else {
r--;
}
}
} else {
for (let i = start; i < nums.length - k + 1; i++) {
if (i === start || (i > start && nums[i] !== nums[i - 1])) {
let temp = nSum(nums, target - nums[i], k - 1, i + 1);
temp.forEach(t => {
t.push(nums[i]);
res.push(t);
});
}
}
}
return res;
}
// another
/**
* @param {number[]} nums
* @param {number} target
* @return {number[][]}
*/
const fourSum = function(nums, target) {
const res = [], n = nums.length
nums.sort((a, b) => a - b)
for(let a = 0; a < n - 3; a++) {
if(a > 0 && nums[a] === nums[a - 1]) continue
for(let b = a + 1; b < n - 2; b++) {
if(b > a + 1 && nums[b] === nums[a + 1]) continue
if(b > a + 1 && nums[b] === nums[b - 1]) continue
const t = target - nums[a] - nums[b]
let l = b + 1, r = n - 1
while(l < r) {
const sum = nums[l] + nums[r]
if(sum < t) l++
else if(sum > t) r--
else {
res.push([nums[a], nums[b], nums[l], nums[r]])
l++
r--
while(l < r && nums[l] === nums[l - 1]) l++
while(l < r && nums[r] === nums[r + 1]) r--
}
}
}
}
return res
};