9-2
Posted tbgatgb
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了9-2相关的知识,希望对你有一定的参考价值。
39. 组合总和
给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
candidates 中的数字可以无限制重复被选取。
说明:
所有数字(包括 target)都是正整数。
解集不能包含重复的组合。
示例 1:
输入: candidates = [2,3,6,7], target = 7,
所求解集为:
[
[7],
[2,2,3]
]
示例 2:
输入: candidates = [2,3,5], target = 8,
所求解集为:
[
[2,2,2,2],
[2,3,3],
[3,5]
]
Python most votes solution:
class Solution(object):
def combinationSum(self, candidates, target):
"""
:type candidates: List[int]
:type target: int
:rtype: List[List[int]]
"""
res = []
candidates.sort()
self.dfs(candidates, target, 0, [], res)
return res
def dfs(self, nums, target, start, path, res):
if target == 0:
res.append(path)
return
for i in xrange(start, len(nums)):
if target < nums[i]:
break
self.dfs(nums, target-nums[i], i, path+[nums[i]], res)
分析:
(1)代码用到了树结构中的DFS(深度优先搜索)。
(2)在代码最开始对candidates进行排序,是为了在递归中,一旦遇到不合适的情形,能够尽早地跳出循环,从而减少代码的运行时间。
(3)如何构建这个递归结构?首先要明白每一次递归,target都要减去nums中的一个数,从而在整个递归调用中,每一次更新后的target控制了程序下一步的导向:
- 如果target == 0,要return;
- 如果target < nums[i],就没有再往深处搜索的必要了(因为nums是有序的,深度优先搜索的顺序是由小到大的),所以此时程序应尽早退出循环,往广度的方向进行搜索。
(4)在每一轮递归中,要传递哪些参数?
- 首先必须要有nums,因为我们在每一轮递归中都要用到nums中的数,而且在传递的过程中我们不能修改nums(因为程序要从最深的节点逐级返回);
- 其次,必须要有target,它控制了程序下一步运行的方向。为了能够使target抵达递归基,同时代码采用的又是DFS策略,因此每次递归往深处进行时,target都要减去nums中的一个数(在满足条件的情况下是由最小的数减到最大的数,这一过程是由for循环实现的);
- 再次,上一次递归的索引 i 也是要传递的,这可以避免不必要的搜索过程。例如,当程序已经搜索至 2 -> 3 时,利用索引 i 可以保证下一次搜索的数字是从3开始而不是从2开始的(因为在2 -> 3 -> 2之间,已经有过 2 -> 2 -> 3了,传递索引 i 可以避免这类重复搜索的情况);
- 接着,要传递当前的搜索路径,在每次递归中,它也是动态变化的:每往下递归一层,它的路径中就增添一项;每往上回退一层,就回到先前的那个路径。传递该路径的目的是一旦找到符合题意的路径组合,就将它保存到res中。
- 最后要传递res,它保存了所有满足要求的路径,用于最终函数结果的返回。
以上是关于9-2的主要内容,如果未能解决你的问题,请参考以下文章
Greenplum 实时数据仓库实践——Greenplum监控与运维