4 sum

FROM: https://leetcode.com/problems/4sum/

 

Given an array S of n integers, are there elements abc, 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.

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]
]

The simplest and most intuitive way is to loop through four layers, add them in turn, and find the quaternion array that meets the conditions. The time complexity is N*N*N*N;

Of course there are faster algorithms;

Consider first a way to find a two-element array that adds up to a given number:

1. Sort the array;

2. The two pointers, i & j, move from the beginning and the end, respectively, considering only the simplest case:

    a) nums(i) + nums(j) > target; because already sorted, so there is nums(i) + nums(j - 1) < nums(i) + nums(j), so move the pointer j forward by 1 For, it is possible to get a number equal to the target;

    b) nums(i) + nums(j) < target; correspondingly move i backward by 1 bit;

    c) nums(i) + nums(j) == target; At this time, a set of numbers of compound conditions have been found, and i and j are shifted by one place;

Through the above steps, the problem of 2 sum can be solved in O(N) time;

Then consider the problem of finding triples that add up to a given number:

1. Sort;

2. Starting from the front (or from the back), process each number in turn;

3. From the subarray after (or before) the given number, find the two-tuple that adds up to target - nums(i);

4. Expand the 2-tuple obtained in the third step plus nums(i) into a 3-tuple;

 

Then the solutions of quadruples and triples are the same, first find the triples, and then expand into quadruples;

 

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
}

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325737278&siteId=291194637
sum