title: backtrack解决问题一点总结
date: 2018-2-5 21:18:40
categories:
- Algorithm
tags:
- Algorithm
算法设计与分析中就学过回溯法(递归,迭代),可是一
遇到问题,还是没有建立起使用回溯的思想。在子集包含,字符串重建,序列,等问题中都非常好用。
public class leetcode046_Permutations {
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] nums = {1,2,3};
System.out.println(permute(nums));
}
public static List<List<Integer>> permute(int[] nums) {
List<List<Integer>> list = new ArrayList<>();
backtrack(list, new ArrayList<>(), nums);
return list;
}
public static void backtrack(List<List<Integer>> list, List<Integer> templist, int[] nums){
if (templist.size() == nums.length) {
list.add(new ArrayList<>(templist));// 符合条件的加入进去
}
else {
for (int i = 0; i < nums.length; i++) {
if (templist.contains(nums[i])){ // 这个判断是否包含重复 也是及其精妙啊
continue;
}
templist.add(nums[i]);
backtrack(list, templist, nums);
templist.remove(templist.size() - 1);
}
}
}
}
需要考虑重复问题
public class leetcode047_Permutations2 {
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] nums = {3,3,0,3};
System.out.println(permuteUnique(nums));
}
public static List<List<Integer>> permuteUnique(int[] nums) {
List<List<Integer>> list = new ArrayList<>();
Arrays.sort(nums);
boolean[] flags = new boolean[nums.length]; // 默认都是 false
backtrack(list, new ArrayList<>(), nums, flags);
return list;
}
public static void backtrack(List<List<Integer>> list, List<Integer> templist, int[] nums, boolean[] flags) {
if (templist.size() == nums.length) {
list.add(new ArrayList<>(templist));
}
else {
for (int i = 0; i < nums.length; i++) {
if (flags[i]) {
continue; // 如果这个元素使用过了,就不再加入进去
}
if (i > 0 && nums[i] == nums[i - 1] && !flags[i - 1]){
continue; //
}
flags[i] = true;
templist.add(nums[i]);
backtrack(list, templist, nums, flags);
templist.remove(templist.size() - 1);
flags[i] = false;
}
}
}
}
---
## SubSet1
```java
public class leetcode078_SubSet {
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] nums = {1,2,3};
System.out.println(subsets(nums));
}
public static List<List<Integer>> subsets(int[] nums) {
// 排序之后循环 题目关键之处在于 distinct integers 意味着 数字不会重复,降低了难度
List<List<Integer>> answer = new ArrayList<List<Integer>>();
answer.add(new ArrayList<Integer>());
for (int i = 0;i < nums.length;i++){
List<List<Integer>> temp = new ArrayList<List<Integer>>();
for (List<Integer> x:answer){
List<Integer> y = new ArrayList<Integer>(x);
y.add(nums[i]);
temp.add(y);
}
answer.addAll(temp);
}
return answer;
}
}
public class leetcode090_Subsets2 {
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] nums = {1,2,2};
System.out.println(subsetsWithDup(nums));
}
public static List<List<Integer>> subsetsWithDup(int[] nums) {
List<List<Integer>> list = new ArrayList<>();
Arrays.sort(nums);
backtrack(list, new ArrayList<>(), nums, 0);
return list;
}
public static void backtrack(List<List<Integer>> list, List<Integer> tempList, int[] nums,int start) {
list.add(new ArrayList<>(tempList));
for (int i = start; i < nums.length; i++) {
if (i > start && nums[i] == nums[i - 1]) {
continue;
}
tempList.add(nums[i]);
backtrack(list, tempList, nums, i + 1);
tempList.remove(tempList.size() - 1);
}
}
}
public class leetcode077_Combinations {
public static void main(String[] args) {
System.out.println(combine(4,2));
}
// 排列组合问题 使用回溯法
// Backtracking Solution Java
public static List<List<Integer>> combine(int n, int k) {
List<List<Integer>> res = new ArrayList<List<Integer>>();
List<Integer> test = new ArrayList<Integer>();
combine1(res,test,1,n,k);
return res;
}
public static void combine1(List<List<Integer>> res,List<Integer> temp,int start,int n,int k){
if (k == 0){
res.add(new ArrayList<Integer>(temp));
return ;
}
for (int i = start;i <= n; i++){
temp.add(i);
combine1(res,temp, i + 1,n,k - 1);
temp.remove(temp.size() - 1);
}
}
}
---
## Combination Sum II
/**
* @author 作者 : coderlong
* @version 创建时间:2018年2月5日 下午4:29:33
* 类说明: 其实这道题,和之前的那道combinationSum是一样的,只不过现在需要考虑重复的问题
*/
public class leetcode040_CombinationSum2 {
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] candidates = {10, 1, 2, 7, 6, 1, 5};
System.out.println(combinationSum2(candidates, 8));
}
public static List<List<Integer>> combinationSum2(int[] candidates, int target) {
List<List<Integer>> list = new ArrayList<>();
Arrays.sort(candidates);
backtrack(list, new ArrayList<>(), candidates, target, 0);
return list;
}
public static void backtrack(List<List<Integer>> list, List<Integer> templist, int[] candidates, int remain,int start) {
if (remain < 0) {
return ;
}
if (remain == 0) {
list.add(new ArrayList<>(templist));
return;
}
for (int i = start; i < candidates.length; i++) {
if (i > start && candidates[i] == candidates[i - 1]) {
continue; // 忽略重复的元素
}
templist.add(candidates[i]);
backtrack(list, templist, candidates, remain - candidates[i], i + 1);
templist.remove(templist.size() - 1);
}
}
}