FROM: https://leetcode.com/problems/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: The solution set must not contain duplicate quadruplets.app
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] ]
最簡單直觀的辦法就是四層循環,依次相加,找出符合條件的四元數組便可,時間複雜度爲N*N * N * N;指針
固然有更快的算法;code
先考慮找出相加等於給定數字的二元數組的辦法:排序
1. 將數組排序;three
2. 兩個指針, i & j, 分別從頭和尾開始移動, 只考慮最簡單的狀況:element
a) nums(i) + nums(j) > target; 由於已經排序, 因此有nums(i) + nums(j - 1) < nums(i) + nums(j), 因此將指針j向前移動1爲, 有可能獲得和target相等的數字;leetcode
b) nums(i) + nums(j) < target; 相應的將i向後移動1位;get
c) nums(i) + nums(j) == target; 這時已經找到一組複合條件的數字,分別將i 和j移動一位;
經過以上的步驟能夠O(N)的時間內解決2 sum的問題;
而後考慮找出相加等於給定數字的三元組的問題:
1. 排序;
2. 從前(或者從後)開始,依次處理每一個數字;
3. 從給定數字後面(或者前面)的子數組中, 尋找相加等於target - nums(i)的二元組;
4. 將第三步獲得的二元組加上nums(i)擴充爲3元組;
那麼四元組和三元組的解法是一致的, 先找到三元組, 而後擴充爲四元組;
package main import ( "fmt" "sort" ) func main() { nums := []int{1, 0, -1, 0, -2, 2} result := fourSum(nums, 0) for _, x := range result { fmt.Printf("%v\n", x) } } func fourSum(nums []int, target int) [][]int { sort.Ints(nums) result := make([][]int, 0, 10) for i := len(nums) - 1; i > 2; i-- { if i < len(nums)-1 && nums[i] == nums[i+1] { continue } xs := threeSum(nums[:i], target-nums[i]) for _, x := range xs { result = append(result, append(x, nums[i])) } } return result } func threeSum(nums []int, target int) [][]int { result := make([][]int, 0, 10) for i := len(nums) - 1; i > 1; i-- { if i < len(nums)-1 && nums[i] == nums[i+1] { continue } xs := twoSum(nums[:i], target-nums[i]) for _, x := range xs { result = append(result, append(x, nums[i])) } } return result } func twoSum(nums []int, target int) [][]int { result := make([][]int, 0, 10) for i, j := 0, len(nums)-1; i < j; { if i > 0 && nums[i] == nums[i-1] { i++ continue } if j < len(nums)-1 && nums[j] == nums[j+1] { j-- continue } sum := nums[i] + nums[j] if sum < target { i++ } else if sum > target { j-- } else { result = append(result, []int{nums[i], nums[j]}) i++ j-- } } return result }