回溯算法的一点总结


title: backtrack解决问题一点总结
date: 2018-2-5 21:18:40
categories:
- Algorithm
tags:
- Algorithm


算法设计与分析中就学过回溯法(递归,迭代),可是一
遇到问题,还是没有建立起使用回溯的思想。在子集包含,字符串重建,序列,等问题中都非常好用。

Permutations1

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);
			}
		}
	}

}

Permutations2

需要考虑重复问题

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;
		 
	  }
}

Subset2

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);
		}
	}

}


Combination Sum

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);
		 }
	}

}

你可能感兴趣的:(java,algorithm)