39. Combination Sum
来源:互联网 发布:阿里云os5.1系统root 编辑:程序博客网 时间:2024/04/30 20:49
QUESTION
Given a set of candidate numbers (C) and a target number (T), find all unique combinations in C where the candidate numbers sums to T.
The same repeated number may be chosen from C unlimited number of times.
Note
- All numbers (including target) will be positive integers.
- The solution set must not contain duplicate combinations.For example, given candidate set [2, 3, 6, 7] and target 7,
A solution set is:
[ [7], [2, 2, 3]]
THOUGHTS
这道题完完全全是自己做出来的,略开心啊。不过还是调试了几次,利用的是回溯法加上dfs,这种做法应该很熟悉了,上课看书是理解不了的,只有多做题才能熟练掌握,不是提倡题海战术,只不过要多做题多思考多总结。给出一列数组,还有一个目标值,求所有和为目标值的集合。其实dfs就是一棵树啊,回溯只不过是借助这种结构进行剪枝。
CODE
public class Solution { public List<List<Integer>> combinationSum(int[] candidates, int target) { List<List<Integer>> res = new ArrayList<List<Integer>>(); if(candidates == null || candidates.length == 0) return res; List<Integer> temp = new ArrayList<Integer>(); Arrays.sort(candidates); dfs(candidates,target,res,temp,0,0); return res; } public void dfs(int[] nums,int target,List<List<Integer>> res,List<Integer> temp,int sum,int start){ if(sum == target){ sum = 0; res.add(new ArrayList<Integer>(temp)); return; } else if(sum > target){ sum = 0; return; } for(int i = start;i < nums.length;i++){ temp.add(nums[i]); sum += nums[i]; dfs(nums,target,res,temp,sum,i); sum -= nums[i]; temp.remove(temp.size() - 1); while(i < nums.length - 1 && nums[i] == nums[i + 1]) i++; } }}
RESULT
runtime complexity is O(n^2),space complexity is O(1).
#
SPECIAL ATTENTION
- 在进行处理之前要先排序,因为可能会出现[3,2,2]的情况,答案给出的是[2,2,3]。
- 排序之后,也要考虑结果重复的情况,比如candidates[] = {2,2,3},target = 5;那么处出现[2,3],[2,3]俩个结果,最好是在处理的时候跳过这种情况。方法就是如果下一个处理数和本次处理数相同,则跳过。
- 还要考虑出现的一种情况是,结果中包含[2,2,3],[2,3,2],[3,2,2]为什么我们从小到大排序了还会出现这种情况呢?这是因为我们进行下次递归的时候不是从本节点以后开始的,而是又从0开始的,解决方法是,设置一个参数start,下次进行递归的时候从start开始,如果不允许结果重复,那么就从start + 1开始递归。很尴尬下道题就是这么出的,所以秒解。还需要注意的一点是当开始递归的时候,传递的参数不是start而是变成了i;
二刷
时间复杂度还是不会算,网上看到大神的答案也没看懂。
接下来就是复杂度分析。这道题的复杂度分析起来比较复杂….一刷的时候就没有好好思考。
首先我们假设这个数组candidate长为n, 在其中有m个元素小于target,假设T(n) = find(target),那么我们可以根据程序得到以下分析结果:
DFS Level 0: 我们首次调用辅助函数, 这一层的count = 1
DFS Level 1: 这时候我们进入了辅助函数的for循环,在for循环里我们有一个pruning,当candidate[i] > target的时候,返回,所以这一层我们只对小于target的元素进行下一层DFS,如我们假设的,结果为m
DFS Level 2: 根据代码,我们上一层有一个target -= num,所以这一层的target其实都不一样。
假设我们对candidate中最小的元素min进行分析,这时候新的target1 = target - min,此时我们要继续计算在candidate数组中有多少元素小于新的target1,假设这个数目为m1,则在这一层我们要对小于target1的m1个数组进行下一层的DFS
假如我们考虑其他非min的元素来计算总的复杂度时, 这时候两层总共要进行1 + m(m1 + m2 + m3 + … + mn)次调用。
由于每一层的target和m都在改变,以我的水平比较难计算出一个漂亮的公式,那么我就想办法简化一下:
这里递归的最大深度是d= target / min, 就是最深我们可以到 target / min这么多层DFS
Branching factor b = m, m是candidate数组里小于等于target的distinct元素的个数。 其实这里多算了,每一层的m都在减少,而且是不规则减少
我们利用DFS公式可以算出这里的Time Complexty = O(md), Space Complexity = O(m)
这只是一个worst case scenario, 更精确的计算还需要再花时间。
这是大神的csdn
二刷CODE
public class Solution { public List<List<Integer>> combinationSum(int[] candidates, int target) { List<List<Integer>> result = new ArrayList<List<Integer>>(); Arrays.sort(candidates); List<Integer> temp = new ArrayList<Integer>(); if(candidates == null || candidates.length == 0) return result; sumHelper(result,temp,candidates,target,0); return result; } public void sumHelper(List<List<Integer>> res,List<Integer> temp,int[] nums,int target,int index){ if(target == 0){ res.add(new ArrayList(temp)); return; } if(target < 0) //这里之所以是return不是continue是因为数组是经过排序的 //如果当前的元素大于目标数,就没有必要再继续了,后面的肯定也大于 return; for(int i = index;i < nums.length;i++){ if(nums[i] > target) return; //注意这里是i大于index if(i > index && nums[i] == nums[i - 1]) continue; temp.add(nums[i]); target -= nums[i]; sumHelper(res,temp,nums,target,i); temp.remove(temp.size() - 1); target += nums[i]; } }}
- 39. Combination Sum && 40. Combination Sum II
- 39. Combination Sum &&40. Combination Sum II
- [LeetCode]39.Combination Sum
- LeetCode --- 39. Combination Sum
- LeetCode 39.Combination Sum
- [Leetcode] 39. Combination Sum
- 39. Combination Sum
- 39. Combination Sum
- Leetcode-39.Combination Sum
- LeetCode 39. Combination Sum
- [LeetCode]39. Combination Sum
- 39. Combination Sum LeetCode
- [leetcode] 39. Combination Sum
- 39. Combination Sum
- 39. Combination Sum
- leetcode 39. Combination Sum
- 【leetcode】 39. Combination Sum
- 39. Combination Sum(backtracking)
- test
- LeNet模型简介
- Java NIO中Selector类源码
- 不能相邻的字符对
- 64. Minimum Path Sum
- 39. Combination Sum
- 216. Combination Sum III
- Linux下的一些问题收集及解决方法(一)
- 初探swift语言的学习笔记二(可选类型?和隐式可选类型!)
- C# Regex类详解
- Spark安装
- Python语言学习讲解五:列表(List)操作方法详解
- Android开发视频源码
- kernel version 367.48. does not match DSO version 367.57