018-4sum

作者: 英武 | 来源:发表于2019-04-12 16:50 被阅读0次

4 sum

Given an array nums of n integers and an integer target, are there elements a, b, c, and d in nums 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.

Example:

Given array nums = [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]
]

先来一个直接计算的:

class Solution(object):
    def fourSum(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[List[int]]
        """
        # from collections import defaultdicts
        numLen, res, d = len(nums), set(), {}
        if numLen < 4: return []
        nums.sort()
        for p in range(numLen):
            for q in range(p+1, numLen):
                if nums[p]+nums[q] not in d:
                    d[nums[p]+nums[q]] = [(p,q)]
                else:
                    d[nums[p]+nums[q]].append((p,q))
        for i in range(numLen):
            for j in range(i+1, numLen-2):
                T = target-nums[i]-nums[j]
                if T in d:
                    for k in d[T]:
                        if k[0] > j: res.add((nums[i],nums[j],nums[k[0]],nums[k[1]]))
        return [list(i) for i in res]

再来一个能够解决 k sum 的方案,而且速度超级快:

class Solution:
    def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
        def findNsum(l, r, target, N, result, results):
            if r-l+1 < N or N < 2 or target < nums[l]*N or target > nums[r]*N:  # early termination
                return
            if N == 2: # two pointers solve sorted 2-sum problem
                while l < r:
                    s = nums[l] + nums[r]
                    if s == target:
                        results.append(result + [nums[l], nums[r]])
                        l += 1
                        while l < r and nums[l] == nums[l-1]: # remove duplicate
                            l += 1
                    elif s < target:
                        l += 1
                    else:
                        r -= 1
            else: # recursively reduce N
                for i in range(l, r+1):
                    if i == l or (i > l and nums[i-1] != nums[i]):
                        findNsum(i+1, r, target-nums[i], N-1, result+[nums[i]], results)

        nums.sort()
        results = []
        findNsum(0, len(nums)-1, target, 4, [], results)
        return results

上面的参数有点多,可以简化一下,但是速度就慢了:

class Solution:
    def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
        nums.sort()
        def ksum(num, k, target):
            i = 0
            result = set()
            if k == 2:
                j = len(num) - 1
                while i < j:
                    if num[i] + num[j] == target:
                        result.add((num[i], num[j]))
                        i += 1
                    elif num[i] + num[j] > target:
                        j -= 1
                    else:
                        i += 1
            else:
                while i < len(num) - k + 1:
                    newtarget = target - num[i]
                    subresult = ksum(num[i+1:], k - 1, newtarget)
                    if subresult:
                        result = result | set( (num[i],) + nr for nr in subresult)
                    i += 1

            return result

        return [list(t) for t in ksum(nums, 4, target)]

再来一个迭代器版本的, 同样慢:

class Solution:
    def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
        nums.sort()
        def ksum(num, k, target):
            i = 0
            if k == 2:
                j = len(num) - 1
                while i < j:
                    if num[i] + num[j] == target:
                        yield (num[i], num[j])
                        i += 1
                    elif num[i] + num[j] > target:
                        j -= 1
                    else:
                        i += 1
            else:
                while i < len(num) - k + 1:
                    newtarget = target - num[i]
                    for sub in ksum(num[i+1:], k - 1, newtarget):
                        yield (num[i],) + sub
                    i += 1

        return [list(t) for t in set(ksum(nums, 4, target))]

再来一个官网的解法,有点麻烦,但是很好理解,就是转化为3sum,然后2sum:

class Solution:
    def twoSum(self, nums, target, l, r):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """

        n = len(nums[l : r+1])
        if n < 2:
            return list()

        start = nums[l - 1]
        dict1 = dict()
        ret = list()
        for i in range(l, r+1):
            other = target - nums[i]
            if other in dict1:
                ret.append([start, other, nums[i]])
            dict1[nums[i]] = i

        return ret

    # nums[l...r] 中返回 a+b+c=target
    def threeSum(self, nums, target, l, r):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """

        n = len(nums[l : r+1])
        if n < 3:
            return list()

        start = nums[l-1]
        ret = list()
        for i in range(l, r+1):
            if nums[i] > 0 and target <= 0:
                break
            if (i >= l+1 and nums[i] == nums[i-1]):
                continue
            ll = self.twoSum(nums, target-nums[i], i+1, r)
            if (ll == list()):
                continue
            for i in ll:
                i.insert(0, start)
                ret.append(i)
        return ret

    def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
        n = len(nums)
        if n < 4:
            return []
        nums.sort()
        ret = set()
        for i in range(n):
            ll = self.threeSum(nums, target-nums[i], i+1, n-1)
            if ll == list():
                continue
            for l in ll:
                ret.add(tuple(l))
        return list(ret)

相关文章

  • 018-4sum

    4 sum Given an array nums of n integers and an integer ta...

网友评论

      本文标题:018-4sum

      本文链接:https://www.haomeiwen.com/subject/cqxhwqtx.html