【leetcode】各种sum

18. 四数之和 

class Solution(object):
    def fourSum(self, nums, target):
        lens = len(nums)
        nums.sort()
        res = set()
        dicinum = {}
        # 先求数字的两两之和,存到一个list里。
        # 再两次for循环,将4sum转为2sum
        # 2sum时,在list中找是否存在元素。
        for i in range(lens-1):
            for j in range(i+1,lens):
                key = nums[i]+nums[j]
                if key not in dicinum:
                    dicinum[key]= [(i,j)]
                else:
                    dicinum[key].append((i,j))
        # print(dicinum)

        for i in range(lens-1): # for i in range(2,lens-1):
            # 转为3数之和
            for j in range(i+1,lens-2):
                # 转为2数之和
                diff2 = target - nums[i] - nums[j]
                if diff2 in dicinum:
                    for index in dicinum[diff2]:
                        # print(index) #(4, 5) (2, 5)
                        if index[0]>j: # 不能重复取
                            res.add((nums[i], nums[j], nums[index[0]], nums[index[1]]))
        print(res)
        # {(-2, -1, 1, 2), (-2, 0, 0, 2), (-1, 0, 0, 1)}
        return [list(i) for i in res]
        # [[-2, -1, 1, 2], [-2, 0, 0, 2], [-1, 0, 0, 1]]
# 超时
class Solution(object):
    def fourSum(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[List[int]]
        """
        nums.sort()
        res = set()
        dicinum = {}
        # 先求数字的两两之和,存到一个list里。
        # 再两次for循环,将4sum转为2sum
        # 2sum时,在list中找是否存在元素。
        for i in range(len(nums)):
            for j in range(i+1,len(nums)):
                key = nums[i]+nums[j]
                if key not in dicinum.keys():
                    dicinum[key]= [(i,j)]
                else:
                    dicinum[key].append((i,j))
        # print(dicinum)
        for i in range(len(nums)):
            # 转为3数之和
            for j in range(i+1,len(nums)-2):
                # 转为2数之和
                diff2 = target - nums[i] - nums[j]
                if diff2 in dicinum:
                    for index in dicinum[diff2]:
                        # print(index) #(4, 5) (2, 5)
                        if index[0]>j: # 不能重复取
                            res.add((nums[i], nums[j], nums[index[0]], nums[index[1]]))
        print(res)
        # {(-2, -1, 1, 2), (-2, 0, 0, 2), (-1, 0, 0, 1)}
        return [list(i) for i in res]
        # [[-2, -1, 1, 2], [-2, 0, 0, 2], [-1, 0, 0, 1]]

N sum

把4数和分解为2数和的递归,并且上升到可以解决任意N数和

class Solution(object):
    def fourSum(self, nums, target):
        def findNsum(left, right, target, N, tmp_res, res):
            if right - left + 1 < N or N < 2 or target < nums[left] * N or target > nums[
                right] * N:  # early termination
                return
            if N == 2:  # 2数和
                while left < right:
                    total = nums[left] + nums[right]
                    if total == target:
                        res.append(tmp_res + [nums[left], nums[right]])
                        left += 1
                        while left < right and nums[left] == nums[left - 1]:
                            left += 1
                    elif total < target:
                        left += 1
                    else:
                        right -= 1
            else:  # 递归
                for i in range(left, right + 1):
                    if i == left or (i > left and nums[i - 1] != nums[i]):
                        findNsum(i + 1, right, target - nums[i], N - 1, tmp_res + [nums[i]], res)

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

参考:

【算法】2SUM/3SUM/4SUM问题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值