算法题 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)

 

posted @ 2018-08-29 09:27  Fintech带你飞  阅读(844)  评论(0编辑  收藏  举报