算法题 21 findNSum (好未来,LeetCode,牛客网)
一、三数之和:LeetCode 15
给定一个包含 n 个整数的数组 nums
,判断 nums
中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。
注意:答案中不可以包含重复的三元组。
例如, 给定数组 nums = [-1, 0, 1, 2, -1, -4], 满足要求的三元组集合为: [ [-1, 0, 1], [-1, -1, 2] ]
解题代码一:
class Solution: def threeSum(self, nums): """ :type nums: List[int] :rtype: List[List[int]] """ result=[] nums.sort() for i in range(len(nums)-2): #下标i表示三个数中的第一个数 if i>0 and nums[i]==nums[i-1]:#遇到重复的数就直接跳过,避免重复计算三元组 continue #下标j表示三个数中的第二个,从i+1开始递增;下标k表示三个数中的第三个,从len(nums)-1递减 j,k=i+1,len(nums)-1 while j<k: sum0=nums[i]+nums[j]+nums[k] if sum0<0: j+=1 elif sum0>0: k-=1 else: result.append([nums[i],nums[j],nums[k]]) #如果此时j和后面的数重复,k和前面的数重复记得要直接跳过 while j<k and nums[j+1]==nums[j]: j+=1 while j<k and nums[k-1]==nums[k]: k-=1 j+=1 k-=1 return result
解题代码二:更通用,适用于Nsum
class Solution: def threeSum(self, nums): """ :type nums: List[int] :rtype: List[List[int]] """ # method 2:通用方法 nums.sort() results=[] self.findNSum(nums,0,3,[],results) return results def findNSum(self,nums,target,N,result,results): if N<2 or len(nums)<N or target<nums[0]*N or target>nums[-1]*N: return if N==2: j,k=0,len(nums)-1 while j<k: s=nums[j]+nums[k] if s<target: j+=1 elif s>target: k-=1 else: results.append(result+[nums[j],nums[k]]) while j<k and nums[j+1]==nums[j]: j+=1 while j<k and nums[k-1]==nums[k]: k-=1 j+=1 k-=1 else: # 共有len(nums)-N+1个N元组 for i in range(len(nums)-N+1): if i==0 or (i>0 and nums[i-1]!=nums[i]): self.findNSum(nums[i+1:],target-nums[i],N-1,result+[nums[i]],results) return
二、四数之和 LeetCode
给定一个包含 n 个整数的数组 nums
和一个目标值 target
,判断 nums
中是否存在四个元素 a,b,c 和 d ,使得 a + b + c + d 的值与 target
相等?找出所有满足条件且不重复的四元组。
注意:
答案中不可以包含重复的四元组。
示例:
给定数组 nums = [1, 0, -1, 0, -2, 2],和 target = 0。 满足要求的四元组集合为: [ [-1, 0, 0, 1], [-2, -1, 1, 2], [-2, 0, 0, 2] ]
解题代码:(通用,适合于NSum)
class Solution: def fourSum(self, nums, target): """ :type nums: List[int] :type target: int :rtype: List[List[int]] """ nums.sort() results=[] self.findNSum(nums,target,4,[],results) return results def findNSum(self,nums,target,N,result,results): if N<2 or len(nums)<N or target<nums[0]*N or target>nums[-1]*N: return if N==2: j,k=0,len(nums)-1 while j<k: s=nums[j]+nums[k] if s<target: j+=1 elif s>target: k-=1 else: results.append(result+[nums[j],nums[k]]) while j<k and nums[j+1]==nums[j]: j+=1 while j<k and nums[k-1]==nums[k]: k-=1 j+=1 k-=1 else: # 共有len(nums)-N+1个N元组 for i in range(len(nums)-N+1): if i==0 or (i>0 and nums[i-1]!=nums[i]): self.findNSum(nums[i+1:],target-nums[i],N-1,result+[nums[i]],results) return
三、牛客网 求和
链接:https://www.nowcoder.com/questionTerminal/11cc498832db489786f8a03c3b67d02c
来源:牛客网
输入两个整数 n 和 m,从数列1,2,3.......n 中随意取几个数,使其和等于 m ,要求将其中所有的可能组合列出来
输入描述:
每个测试输入包含2个整数,n和m
输出描述:
按每个组合的字典序排列输出,每行输出一种组合
示例1
输入
5 5
输出
1 4
2 3
5
解法一:改造NSum
n, m = [int(x) for x in input().split()] def findNSum(nums, target, N, result, results): if N < 2 or len(nums) < N or target < nums[0]*N or target > nums[-1]*N: return if N == 2: j, k = 0, len(nums)-1 while j < k: s = nums[j]+nums[k] if s < target: j += 1 elif s > target: k -= 1 else: results.append(result+[nums[j], nums[k]]) while j < k and nums[j+1] == nums[j]: j += 1 while j < k and nums[k-1] == nums[k]: k -= 1 j += 1 k -= 1 else: # 共有len(nums)-N+1个N元组 for i in range(len(nums)-N+1): if i == 0 or (i > 0 and nums[i-1] != nums[i]): findNSum(nums[i+1:], target-nums[i], N-1, result+[nums[i]], results) return results = [] nums = range(1, n+1) for i in range(1, n+1): if i == m: results.append([i]) for i in range(2, n+1): findNSum(nums, m, i, [], results) res=sorted(results) for arr in res: for i in range(len(arr)): if i==len(arr)-1: print(arr[i]) else: print(arr[i],end=' ')
解法三:DFS 递归
n,m=[int(x) for x in input().split()] def dfs(res,s,temp,n,m,k): if s==m: if temp not in res: res.append(temp) for i in range(len(temp)): if i!=len(temp)-1: print(temp[i],end=' ') else: print(temp[i]) if k>n: return for i in range(k,n+1): if s+i>m: break else: dfs(res,s+i,temp+[i],n,m,i+1) res=[] dfs(res,0,[],n,m,1)