15. 三数之和(筛选数据)
给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。
注意:答案中不可以包含重复的三元组。
例如, 给定数组 nums = [-1, 0, 1, 2, -1, -4],
满足要求的三元组集合为:
[
[-1, 0, 1],
[-1, -1, 2]
]
1/**
2 * @param {number[]} nums
3 * @return {number[][]}
4 */
5
6var threeSum = function (nums) {
7 // 去重到每个最多只剩两个(如果是0, 至多3个)
8 nums = unique(nums)
9 if (nums.length < 3) return [];
10
11 var r = [];
12 nums.sort((a, b) => a - b);
13
14 for (var i = 0; i < nums.length - 2; i++) {
15 var newNums = nums.slice(i + 1);
16
17 // a + b + c = 0 => a + b = -c 将三数之和转 化为 两数之和
18 var a = twoSum(newNums, nums[i]);
19 if (a.length !== 0) r = r.concat(a)
20 }
21
22 return depute(r)
23}
24
25// 筛选数据至每个数据出现不超过两次(0三次)
26/**
27 * @param {number[]} nums
28 * @return {number[]}
29 */
30var unique = function(nums) {
31 // 出现次数不超过2次(如果是0那就3次)
32 var r = [], r1 = []
33 for(var i=0; i<nums.length; i++) {
34 if(r.indexOf(nums[i]) === -1){
35 r.push(nums[i])
36 nums.splice(i, 1)
37 i--
38 }
39 }
40
41 for(var i=0; i<nums.length; i++) {
42 if(r1.indexOf(nums[i]) === -1){
43 r1.push(nums[i])
44 nums.splice(i, 1)
45 i--
46 }
47 }
48
49 var r = r.concat(r1)
50
51 // 如果还有 0
52 for(var i=0; i<nums.length; i++) {
53 if(nums.indexOf(0) !== -1) {
54 r.push(0)
55 break
56 }
57 }
58
59 return r
60}
61
62// 两数之和
63/**
64 * @param {number[]} numbers
65 * @param {number} target
66 * @return {number[]}
67 */
68var twoSum = function (numbers, target) {
69 var r = [], l = numbers.length
70
71 for (var i = 0; i < l - 1;) { // i < l-1 而不是 i < l
72 if (numbers[i] + numbers[l - 1] < -target) {
73 i++
74 continue
75 }
76 if (numbers[i] + numbers[l - 1] > -target) {
77 l--
78 continue
79 }
80 if (numbers[i] + numbers[l - 1] === -target) {
81 var a = [target, numbers[i], numbers[l - 1]]
82 r.push(a)
83 i++
84 l--
85 }
86 }
87
88 return r
89}
90
91// 深度去重
92/**
93 * @param {number[]} a
94 * @return {number[]}
95 */
96var depute = function (a) {
97 for (var i = 0; i < a.length; i++) {
98 a[i] = JSON.stringify(a[i])
99 }
100
101 var newArr = new Set(a)
102 newArr = Array.from(newArr)
103
104 for (var j = 0; j < newArr.length; j++) {
105 newArr[j] = JSON.parse(newArr[j])
106 }
107
108 return newArr
109}