zoukankan      html  css  js  c++  java
  • LeetCode Notes_#18 4Sum

    LeetCode Notes_#18 4Sum

    Contents

    题目

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

    思路和解答

    思路

    问题的内容跟之前的2sum,3sum都是很相似的,仅仅是修改了元素的个数,增加了复杂度(不可以再使用暴力循环的方式,而是要用尽可能少的指针,尽可能少的list访问次数去达成目标)

    • 2sum,两个指针两层循环,遍历所有可能的两两组合形式
    • 3sum,3sumcloest,三个指针,第一个指针遍历所有元素,后面两个指针从左右向中间移动,这并没有遍历到所有情况,但是不会漏掉需要的情况(前提是提前对list排序,然后根据结果的大小动态移动左右指针)
    • 4sum是怎样呢?一定还是需要四个指针的,主要问题在于如何去优化指针遍历元素的方式。

    解答

    #第一版,通过了最简单的case,但是没有考虑到nums里边数字出现重复的情况
    class Solution(object):
        def fourSum(self, nums, target):
            """
            :type nums: List[int]
            :type target: int
            :rtype: List[List[int]]
            """
            res=[]
            nums.sort()
            for i in range(len(nums)-3):
                for j in range(i+1,len(nums)-2):
                    l=j+1
                    r=len(nums)-1
                    while(l<r):
                        sum=nums[i]+nums[j]+nums[l]+nums[r]
                        if sum<target:
                            l+=1
                        if sum>target:
                            r-=1
                        if sum==target:
                            res.append([nums[i],nums[j],nums[l],nums[r]])
                            l+=1
                            r-=1
            return res
    
    #第二版,目的是去除重复,在pycharm上面运行结果没毛病,但是不知道为什么一样的代码在leetcode上面运行结果不一样...
    class Solution(object):
        def fourSum(self, nums, target):
            """
            :type nums: List[int]
            :type target: int
            :rtype: List[List[int]]
            """
            res=[]
            nums.sort()
            for i in range(len(nums)-3):
                if i>0 and nums[i]==nums[i-1]:
                    continue
                for j in range(i+1,len(nums)-2):
                    if j>0 and nums[j]==nums[j-1]:
                        continue
                    l=j+1
                    r=len(nums)-1
                    while(l<r):
                        sum=nums[i]+nums[j]+nums[l]+nums[r]
                        if sum<target:
                            l+=1
                        if sum>target:
                            r-=1
                        if sum==target:
                            res.append([nums[i],nums[j],nums[l],nums[r]])
                            while l < r and nums[l] == nums[l + 1]:  # 两个while语句用来快速移动指针,直到没有出现相邻重复数字
                                l += 1
                            while l < r and nums[r] == nums[r - 1]:
                                r -= 1
                            l+=1
                            r-=1
                return res
    
    #最后还是看一下讨论区大佬的代码吧,使用了递归的方式,可以适用于任意的N-sum的情况
    def fourSum(self, nums, target):
        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]:
                            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
    

    递归的过程大概是这样的:
    一个N-sum问题可以不断地转化为(N-1)-Sum问题,比如说要求4-sum==0

    • 假如先确定第一个数字-2,那么就转化为去找3-sum==2,这时result=[-2],N=3
    • 3-sum=2,假如确定第二个数字是0,那么去找2-sum==2,这时result=[-2,0],N=2
    • N=2就进入2sum的处理方式,直接找到2-sum==2的结果[0,2],这时results.append(result+[0,2]),相当于对results添加了一个[-2,0,0,2]
    • 中间如果遇到肯定不可能的情况就直接pass,以此类推就可以解决任意N-sum问题
  • 相关阅读:
    一台Ubuntu server上安装多实例MySQL
    用VirtualBox构建MySQL测试环境笔记
    Mac点滴
    MySQL复制(三) --- 高可用性和复制
    Linux性能监控的几个工具(转)
    前端读者 | Javascript设计模式理论与实战:状态模式
    前端读者 | 为什么页面跟设计稿差距这么大?是啊!为毛啊?
    前端读者 | 由setTimeout引发的JS引擎运行机制的研究
    前端读者 | Web App开发入门
    前端读者 | 从一行代码里面学点JavaScript
  • 原文地址:https://www.cnblogs.com/Howfars/p/9964918.html
Copyright © 2011-2022 走看看