leetcode刷题_(arr,dfs,recursion)_code39/40(数组中寻找固定元素和1/2)

code39:Combination Sum

Given a set of candidate numbers (candidates) (without duplicates) and a target number (target), find all unique combinations in candidates where the candidate numbers sums to target.

The same repeated number may be chosen from candidates unlimited number of times.

Note:

All numbers (including target) will be positive integers.
The solution set must not contain duplicate combinations.
Example 1:

Input: candidates = [2,3,6,7], target = 7,
A solution set is:
[
[7],
[2,2,3]
]
Example 2:

Input: candidates = [2,3,5], target = 8,
A solution set is:
[
[2,2,2,2],
[2,3,3],
[3,5]
]

解答:
首先想到使用divmod解题:
如果mod!=0,则在数组中遍历找到对应的数组成数组。
如果等于0,则返回div个单元素组成的数组。
咋一看感觉没问题,但是实测时发现,和可以由多个元素组成,这种解法只涵盖了两个。

再次考虑,发现可以使用循环迭代,即每次减去数组一个元素,然后看residual再遍历数组减去元素,知道residual为0时返回所以减去的值作为一个 答案数组。最后将答案数组组合起来形成结果返回。

实现:
发现使用递归将会很简单(类似于backtracking,dfs的解法)
1 定义一个全局变量temp_arr=[]作为最后的结果
2 再带入递归。因为递归要返回每层的值组成的数组。所以设置一个新的参数last_arr用来接收上一个递归里面的现有数组。
3 终止条件:如果residual==0则last_arr+当前元素。然后放入temp_arr中;
或者residual<0 则break(表示不再进行变换,当前的last_arr废弃)
4 递归条件:如果residual>0则last_arr+=当前元素,传入的遍历数组变为当前元素开始(这里注意,先将数组进行排序,然后这样操作下可以避免结果的重复

代码:

class Solution:
    def combinationSum(self, candidates, target: int):
        candidates = sorted(candidates)

        # res_arr = []
        global temp_arr
        temp_arr = []
        self.search(candidates, target, [])
        return temp_arr

    def search(self, candidates, target, last_arr):
        global temp_arr

        for i in range(len(candidates)):

            residual = target - candidates[i]
            #print(residual)
            if residual == 0:
                #print(last_arr + [candidates[i]])
                temp_arr.append(last_arr + [candidates[i]])
                break
            elif residual > 0:
                self.search(candidates[i:], residual, last_arr + [candidates[i]])
            else:
                break

tips:
在遍历循环中有if else判断时,要注意是否加break跳出循环。此时加了break以后,不会再进行之后的操作了,可以减少时间复杂度(同一个数量级但是实际更短)
global变量可以提供远程的修改。如果不想这样操作,可以作为参数传入。

code40: Combination Sum II

Given a collection of candidate numbers (candidates) and a target number (target), find all unique combinations in candidates where the candidate numbers sums to target.

Each number in candidates may only be used once in the combination.

Note:

All numbers (including target) will be positive integers.
The solution set must not contain duplicate combinations.
Example 1:

Input: candidates = [10,1,2,7,6,1,5], target = 8,
A solution set is:
[
[1, 7],
[1, 2, 5],
[2, 6],
[1, 1, 6]
]
Example 2:

Input: candidates = [2,5,2,1,2], target = 5,
A solution set is:
[
[1,2,2],
[5]
]

解答:
类似于上一题,
区别:数组可重复,每个只能使用一次。
可重复使用一次,去重:
1 使用list(set([tuple(t) for t in temp]))来做二维数组的去重
2 或者在判定条件内添加如果前后一样就不用做该元素的操作了

代码:

class Solution:
    def combinationSum2(self, candidates, target: int):
        global temp
        temp = []
        candidates.sort()
        #candidates = list(set(candidates))
        self.search(candidates, target, [])
        #temp = list(set([tuple(t) for t in temp]))
        temp = list(set([tuple(t) for t in temp]))
        return temp

    def search(self, arr, tar, last_arr):
        global temp
        for i in range(len(arr)):
            residual = tar - arr[i]
            if residual == 0:
                temp.append([arr[i]] + last_arr)
                break
            elif residual > 0:
                self.search(arr[i + 1:], residual, last_arr + [arr[i]])
            else:
                break
                
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值