[LeetCode][JavaScript]4Sum
4Sum
Given an array S of n integers, are there elements a, b, c, and d in S such that a + b + c + d = target? Find all unique quadruplets in the array which gives the sum of target.
Note:
- Elements in a quadruplet (a,b,c,d) must be in non-descending order. (ie, a ≤ b ≤ c ≤ d)
- The solution set must not contain duplicate quadruplets.
For example, given array S = {1 0 -1 0 -2 2}, and target = 0. A solution set is: (-1, 0, 0, 1) (-2, -1, 1, 2) (-2, 0, 0, 2)
https://leetcode.com/problems/4sum/
我看Tags里有HashTable,想想三重循环根本用不到,就没有用这个解法。
先两两合并,再用双指针去找结果,写了好多好伤心。
1.合并的结果记入twoSumArr,为了查找再开一个twoSumMap记录下数字的组合。
以题目中的例子来说,twoSumArr -> [-3, -2, -1, 0, 1, 2, 3] , twoSumMap[0] -> [ [-2, 2], [-1, 1], [0, 0] ]
2.在遍历nums的时候,记下每个数字出现的频率,之后的检查要用到,比如这个结果是不合法的[-2, 1, 0 ,1],1只能用一次。
3.最后用双指针遍历twoSumArr求结果,这时会碰到重复的情况。
比如 -1 + 1 = 0, twoSumMap[-1] -> [ [-2, 1], [-1, 0] ], twoSumMap[1] -> [ [-1, 2], [0, 1] ]
在遍历中加一个判断,前一个(-1)里较大的那个数,小于后一个(1)里较小的数,才要记录到结果中,这样就可以去重。
还是写个三重循环比较简单粗暴,这个要考虑好多种情况。
1 /** 2 * @param {number[]} nums 3 * @param {number} target 4 * @return {number[][]} 5 */ 6 var fourSum = function(nums, target) { 7 nums = nums.sort(sorting); 8 var result = []; 9 var countAppear = {}; twoSumMap = {}, twoSumArr = []; 10 var i, j, twoSum; 11 for(i = 0; i < nums.length; i++){ 12 if(!countAppear[nums[i]]){ 13 countAppear[nums[i]] = 1; 14 }else{ 15 countAppear[nums[i]]++; 16 } 17 for(j = i + 1; j < nums.length; j++){ 18 twoSum = nums[i] + nums[j]; 19 if(!twoSumMap[twoSum]){ 20 twoSumArr.push(twoSum); 21 twoSumMap[twoSum] = [[nums[i], nums[j]]]; 22 }else if(!arrContains(twoSumMap[twoSum], nums[i], nums[j])){ 23 twoSumMap[twoSum].push([nums[i], nums[j]]); 24 } 25 } 26 } 27 twoSumArr = twoSumArr.sort(sorting); 28 29 var numA, numB, sum4; 30 for(i = 0, j = twoSumArr.length - 1; i <= j;){ 31 numA = twoSumMap[twoSumArr[i]], numB = twoSumMap[twoSumArr[j]]; 32 sum4 = twoSumArr[i] + twoSumArr[j]; 33 if(sum4 === target){ 34 addCandidate(numA, numB, result); 35 } 36 if(sum4 < target){ 37 i++; 38 }else{ 39 j--; 40 } 41 } 42 return result; 43 44 function verifyResult(arr){ 45 var previous = null, count = 0; 46 for(var i = 0; i < arr.length; i++){ 47 if(arr[i] !== previous){ 48 previous = arr[i]; 49 count = 1; 50 }else{ 51 count++; 52 if(count > countAppear[previous]){ 53 return false; 54 } 55 } 56 } 57 return true; 58 } 59 function addCandidate(numA, numB, result){ 60 var i, j, tmp; 61 for(i = 0; i < numA.length; i++){ 62 for(j = 0; j < numB.length; j++){ 63 if(numA[i][1] <= numB[j][0]){ 64 tmp = [numA[i][0], numA[i][1], numB[j][0], numB[j][1]]; 65 if(verifyResult(tmp)){ 66 result.push(tmp); 67 } 68 } 69 } 70 } 71 } 72 function arrContains(arr, small, large){ 73 for(var i = 0; i < arr.length; i++){ 74 if(arr[i][0] === small && arr[i][1] === large){ 75 return true; 76 } 77 } 78 return false; 79 } 80 function sorting(a, b){ 81 if(a > b){ 82 return 1; 83 }else if(a < b){ 84 return -1; 85 }else{ 86 return 0; 87 } 88 } 89 };