zoukankan      html  css  js  c++  java
  • 【LeetCode每天一题】4Sum(4数之和)

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

    思路


       在看到这道题之后,我第一反应是使用之前求三数之和那样求四数之和,结果也是可行,但是运行结果显示的时间复杂度太高。这里我先将我自己的解决思路写下来

      时间复杂为O(n3),空间复杂为O(1)。

    解决代码

    
    
     1 class Solution:
     2     def fourSum(self, nums, target):
     3         """
     4         :type nums: List[int]
     5         :type target: int
     6         :rtype: List[List[int]]
     7         """
     8         if len(nums) < 4:      # 异常情况,小于四个直接返回
     9             return []
    10         if len(nums) == 4 and sum(nums) == target:     
    11             return [nums]
    12         nums.sort()                 # 先进行排序
    13         res = []
    14         for i in range(len(nums)-3):                # 第一个下标
    15             if i > 0 and nums[i] == nums[i-1]:        # 遇到重复的直接跳过
    16                 continue 
    17             for j in range(i+1, len(nums)-2):         # 第二个下标
    18                 if j > i+1 and nums[j] == nums[j-1]:    # 遇到重复直接跳过
    19                     continue
    20                 start, end = j+1, len(nums)-1         # 另外两个下标,指向头和尾部
    21                 while start < end:                      
    22                     tem = nums[i] + nums[j] + nums[start] + nums[end]       
    23                     if tem - target > 0:              # 进行判断,选择相应的移位
    24                         end -= 1
    25                     elif tem - target < 0:
    26                         start += 1
    27                     else:                              # 找到符合条件的四个数字。
    28                         res.append([nums[i], nums[j], nums[start], nums[end]])    # 将其添加进结果集中
    29                         while start < end and nums[start] == nums[start+1]:       # 相同元素直接跳过。
    30                             start += 1
    31                         while start < end and nums[end] == nums[end-1]:           # 相同元素直接跳过
    32                             end -= 1
    33                         start += 1
    34                         end -= 1
    35         return res
    改进

      上面的算法,在实现之后效率太低,以至于运行结果之超过了百分之10的用户。但是由于自己也想不出什么好的办法,因此取讨论区看了别人的写法,不得不说确实很厉害。下面写上别人给出了一个解决方法,这个方法可以解决N数和的问题。

    解决思路以及代码


       这个问题他的解决思路主要是通过分解,将N数和的问题转化为两数和的问题(递归),并且通过传递变量来记录满足结果的条件。

     1 def fourSum(self, nums, target):
     2     nums.sort()
     3     results = []
     4     self.findNsum(nums, target, 4, [], results) #因为本题是4数之和的问题,所以传入的参数是4,并且将保存满足条件的数字的变量进行传递
     5     return results
     6 
     7 def findNsum(self, nums, target, N, result, results):
     8     if len(nums) < N or N < 2: return             # 数组的长度小于N(N数之和)时或者小于2时,直接返回条件。
    10     # solve 2-sum
    11     if N == 2:                                    # 当N == 2 时,进行判断, 里面的步骤和三数问题中的步骤一样。
    12         l,r = 0,len(nums)-1
    13         while l < r:                  
    14             if nums[l] + nums[r] == target:
    15                 results.append(result + [nums[l], nums[r]])
    16                 l += 1
    17                 r -= 1
    18                 while l < r and nums[l] == nums[l - 1]:
    19                     l += 1
    20                 while r > l and nums[r] == nums[r + 1]:
    21                     r -= 1
    22             elif nums[l] + nums[r] < target:
    23                 l += 1
    24             else:
    25                 r -= 1
    26     else:                                                     # N大于2时进行递归,分解
    27         for i in range(0, len(nums)-N+1):   # careful about range  # 第一个指针位置
    28             if target < nums[i]*N or target > nums[-1]*N:   # 意外情况判定,因为数组是已经排好序的,当第一个元素(最小)乘
    29                 break                              # 以N时,还比target大,那说明,后面的都不满足,直接返回。后面同理。
    30             if i == 0 or i > 0 and nums[i-1] != nums[i]:  #recursively reduce N #从第一个看是遍历,并将相应额结果进行传递。
    31                 self.findNsum(nums[i+1:], target-nums[i], N-1, result+[nums[i]], results)
    32     return





  • 相关阅读:
    【windows】ping对方ip端口,tcping工具
    【mysql】搜索带字符
    【layui】日期选择一闪而过问题
    【转】【linux】查看文件夹大小
    【bat】睡眠2秒
    【mysql】'XXX.XXX.XXX' isn't in GROUP BY问题解决
    【java】获取客户端访问的公网ip和归属地
    【bat】判断字符串是否包含某字符串
    【bat】【windows】win10查看所有wifi密码
    【idea】【sonarlint】指定文件夹扫描
  • 原文地址:https://www.cnblogs.com/GoodRnne/p/10647600.html
Copyright © 2011-2022 走看看