leetcode之回溯backtracing专题1
来源:互联网 发布:mysql创建唯一约束 编辑:程序博客网 时间:2024/05/18 09:41
39 Combination Sum
给一组整数,给一个目标整数。从数组中任意选择几个数,这几个数的和等于目标整数。数组中每个数字可以选择多次。
例如given candidate set [2, 3, 6, 7] and target 7, 返回
[
[7],
[2, 2, 3]
]
思路:数组candidates 中每个数字可以选择一次或者多次。每次在递归中可以选择或者不选择这个数。
首先从0下标开始,每次递归,做个选择。选中当前元素的话:nums[idx]++,表示选择了一个candidates[idx],同时目标值要减小。如果不选择当前元素的话,下标加1,向下遍历。
以下代码可以给进的地方是:可以算出最多可以有多少个candidates[idx],避免不必要的递归。
递归的退出条件要先写好。
public class CombinationSum39 { private List<List<Integer>> resultList = new ArrayList<List<Integer>>(); private int[] nums = null; public List<List<Integer>> combinationSum(int[] candidates, int target) { resultList.clear(); nums = new int[candidates.length]; visit(candidates, target, 0); return resultList; } private void visit(int[] candidates, int target, int idx) { if (target == 0) { List<Integer> result = new ArrayList<Integer>(); for (int i = 0; i < nums.length; i++) { for (int j = 0; j < nums[i]; j++) { result.add(candidates[i]); } } resultList.add(result); return; } if (target < 0 || idx >= candidates.length) { return; } int maxCount = target/candidates[idx]; for(int i=0;i<maxCount;i++){ nums[idx] = i; visit(candidates, target - i*candidates[idx], idx); nums[idx] = 0; } } public static void main(String[] args) { List<List<Integer>> list = new CombinationSum39().combinationSum(new int[]{2,3,6,7}, 7); System.out.println(list); }}
40 Combination Sum II
在39题目的基础上增加了限制条件:数组中每个数只能使用一次。但是数组中有重复的数字。
思路:首先把无限次使用变成只能使用一次。但是这样可能会出现重复的解。解决方法是先排序。
数组 1 1 2 5
选中 0 0 1 1
0 1 1 1
1 0 1 1
1 1 1 1
当遇到前两位是01和10的时候解就会是重复的。这个时候可以选择 01 是有效的或者 10 是有效的。 因为问题可能在第一个1的时候就解决了,所以形成 10 这样的串是很自然的。再者,判断第一位是否已经达到目的,不需要考虑后面的因素。所以最好的选择是选择 01 是无效的。这里非常重要。
还有一个地方是,因为数组中每个元素只能取一次,所以可以选择用boolean数组来标记,不再用数组num做标记。
public class Solution { private List<List<Integer>> resultList = new ArrayList<List<Integer>>(); private int[] nums=null; public List<List<Integer>> combinationSum2(int[] candidates, int target) { resultList.clear(); Arrays.sort(candidates); nums = new int[candidates.length]; visit(candidates,target,0); return resultList; } private void visit(int[] candidates, int target,int idx){ if(target==0){ List<Integer> result = new ArrayList<Integer>(); for(int i=0;i<nums.length;i++){ if(nums[i]>0){ result.add(candidates[i]); } } resultList.add(result); return; } if(target<0 || idx>=candidates.length){ return; } if(idx>0 && candidates[idx]==candidates[idx-1] && nums[idx-1]==0 ){ //不选择当前数据 nums[idx]=0; visit(candidates,target,idx+1); }else{ //选择当前数据 nums[idx]++; visit(candidates,target-candidates[idx],idx+1); //不选择当前数据 nums[idx]--; visit(candidates,target,idx+1); } }}
216 Combination Sum III
从1-9中找到k个数,这k个数的和是target。输出这k个数的组合,组合不能重复。
例如 输入k=3,target=7,则输出 [[1,2,4]]
思路:题中没有明确说明,但从例子来看,每个数字只能使用一次。这和40题类似。一个数组长度为10,里面存的是boolean类型。path[i]=true,表示i被选中。
数组下标 0 1 2 3 4 5 6 7 8 9
值 f t t t f f f f f f =1+2+3
public class Solution { private boolean[] path; private List<List<Integer>> resultList = new ArrayList<List<Integer>>(); public List<List<Integer>> combinationSum3(int k, int n) { path = new boolean[10]; resultList.clear(); robot(1,k,n); return resultList; } private void robot(int idx,int k,int n){ if(n==0 && k==0){ List<Integer> result = new ArrayList<Integer>(); for(int i=0;i<path.length;i++){ if(path[i]){ result.add(i); } } resultList.add(result); } if(n>0 && idx<path.length && idx<=n && k>0){ path[idx]=true; robot(idx+1,k-1,n-idx); path[idx]=false; robot(idx+1,k,n); } }}
- leetcode之回溯backtracing专题1
- leetcode之回溯backtracing专题2
- leetcode之回溯backtracing专题3
- leetcode之回溯backtracing专题4
- leetcode之回溯backtracing专题5
- LeetCode之Backtracing题目汇总
- Backtracing
- 《剑指offer》之回溯法专题
- LeetCode Combinations Problem using backtracing and DFS
- LeetCode 39,40,46,47,78,90 回溯法专题
- 搜索专题之素数环之回溯法
- 【LeetCode】常用算法之回溯法
- leetcode回溯
- leetCode解题报告之Candy(简单回溯)
- 【一、Leetcode数组专题(1)easy】
- LeetCode 回溯算法 backtracking
- leetcode 回溯法 模板
- [leetcode][回溯] Generate Parentheses
- 存储过程中的循环加判断
- 函数的调用过程(栈帧的创建和销毁)
- My-Blog搭建过程:如何让一个网站从零到可以上线访问
- JS 错误处理
- Codeforces Round #415 (Div. 2)-C. Do you want a date?
- leetcode之回溯backtracing专题1
- 计算MTF(SFR)的基本步骤,及sfrmat3和Mitre SFR 1.4进行比较
- 实战mycat读写分离和分库分表(1)-本地mysql多实例搭建
- win7上使用vs2010编译crtmpserver
- C++ 命名规范
- 查看Fabric0.6的默认用户列表方式
- FPGA学习(第8节)-Verilog设计电路的时序要点及时序仿真
- 使用vundle管理vim的插件
- ubuntu下在docker中安装mysql5.6