【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

 






posted @ 2019-04-03 11:12  GoodRnne  阅读(250)  评论(0编辑  收藏  举报