回溯
二叉树和为某一路径值
https://leetcode-cn.com/problems/er-cha-shu-zhong-he-wei-mou-yi-zhi-de-lu-jing-lcof/
class Solution {
List<List<Integer>> ret = new LinkedList<>();
LinkedList<Integer> path = new LinkedList<>();
public List<List<Integer>> pathSum(TreeNode root, int target) {
if(root == null) {
return ret;
}
dfs(root, target);
return ret;
}
public void dfs(TreeNode root, int target) {
if(root == null) {
return ;
}
path.add(root.val);
target -= root.val;
if(target == 0 && root.left == null && root.right == null) {
ret.add(new LinkedList(path));
}
dfs(root.left, target);
dfs(root.right, target);
path.removeLast();
}
}
子集I(无重复元素,返回幂集)
https://leetcode-cn.com/problems/subsets/
class Solution {
public List<List<Integer>> subsets(int[] nums) {
List<List<Integer>> ret = new ArrayList<>();
ret.add(new ArrayList<>());
for (int i = 0; i < nums.length; i++) {
int size = ret.size();
for (int j = 0; j < size; j++) {
List<Integer> tmp = new ArrayList<>(ret.get(j));
tmp.add(nums[i]);
ret.add(tmp);
}
}
return ret;
}
}
子集II含义重复元素,返回幂集)
https://leetcode-cn.com/problems/subsets-ii/
class Solution {
public List<List<Integer>> subsetsWithDup(int[] nums) {
List<List<Integer>> ret = new ArrayList<>();
ret.add(new ArrayList<>());
if(nums == null || nums.length == 0) {
return ret;
}
Arrays.sort(nums);
List<Integer> list = new ArrayList<>();
list.add(nums[0]);
ret.add(list);
if(nums.length == 1) {
return ret;
}
int len = 1;
for(int i = 1; i < nums.length; i++){
int size = ret.size();
if(nums[i] != nums[i-1]){
len = size;
}
for(int j = size - len; j < size; j++){
List<Integer> tmp = new ArrayList(ret.get(j));
tmp.add(nums[i]);
ret.add(tmp);
}
}
return ret;
}
}
字符串的排列
class Solution {
List<String> ret = new ArrayList<>();
public String[] permutation(String s) {
if(s.length() == 0) {
return new String[0];
}
int n = s.length();
char[] str = s.toCharArray();
Arrays.sort(str);
StringBuffer path = new StringBuffer();
boolean[] used = new boolean[n];
dfs(str, n, 0, used, ret, path);
return ret.toArray(new String[0]);
}
public void dfs(char[] str, int len, int depth, boolean[] used, List<String> ret, StringBuffer path ) {
if(depth == len) {
ret.add(path.toString());
}
for(int i = 0; i < len; i++) {
if(used[i]) {
continue;
}
if(i > 0 && str[i] == str[i - 1] && !used[i - 1]) {
continue;
}
path.append(str[i]);
used[i] = true;
dfs(str, len, depth + 1, used, ret, path);
used[i] = false;
path.deleteCharAt(path.length() - 1);
}
}
}
没有重复数字的所有排列(全排列I)
https://leetcode-cn.com/problems/permutations/
class Solution {
public List<List<Integer>> ret = new ArrayList<>();
public List<Integer> path = new ArrayList<>();
public List<List<Integer>> permute(int[] nums) {
if(nums == null || nums.length == 0) {
return ret;
}
int n = nums.length;
boolean[] used = new boolean[n];
dfs(nums, n, 0, used, ret, path);
return ret;
}
public void dfs(int[] nums, int len, int depth, boolean[] used, List<List<Integer>> ret,
List<Integer> path) {
if(depth == len) {
ret.add(new ArrayList<>(path));
}
for(int i = 0; i < nums.length; i++) {
if(!used[i]) {
path.add(nums[i]);
used[i] = true;
dfs(nums, len, depth + 1, used, ret, path);
used[i] = false;
path.remove(path.size() - 1);
}
}
}
}
含有重复数字的所有排列(全排列II)
import java.util.*;
public class Solution {
ArrayList<ArrayList<Integer>> ret = new ArrayList<>();
ArrayList<Integer> path = new ArrayList<>();
public ArrayList<ArrayList<Integer>> permuteUnique(int[] nums) {
if(nums == null || nums.length == 0) {
return ret;
}
Arrays.sort(nums);
int n = nums.length;
boolean[] used = new boolean[n];
dfs(nums, n, 0, used, ret, path);
return ret;
}
public void dfs(int[] nums, int len, int depth, boolean[] used, ArrayList<ArrayList<Integer>> ret, ArrayList<Integer> path) {
if(len == depth) {
ret.add(new ArrayList<>(path));
}
for(int i = 0; i < nums.length; i++) {
if(used[i]) {
continue;
}
if(i > 0 && nums[i] == nums[i - 1] && !used[i - 1]) {
continue;
}
path.add(nums[i]);
used[i] = true;
dfs(nums, len, depth + 1, used, ret, path);
used[i] = false;
path.remove(path.size() - 1);
}
}
}
加起来和为目标的值(一)(没有重复的元素)
https://www.nowcoder.com/questionTerminal/172e6420abf84c11840ed6b36a48f8cd
import java.util.*;
public class Solution {
ArrayList<ArrayList<Integer>> ret = new ArrayList<>();
public ArrayList<ArrayList<Integer>> combinationCount (int target, int[] nums) {
// write code here
dfs(nums, 0, target, new ArrayList<Integer>());
return ret;
}
private void dfs(int[] nums, int depth, int rest, ArrayList<Integer> path) {
if(rest < 0){
return; // 凑过头了,直接返回
}
if(rest == 0){
ret.add(new ArrayList<Integer>(path)); // 刚好凑到目标,返回一组结果
}else{
for(int i = depth; i < nums.length; i++){
path.add(nums[i]);
dfs(nums, i, rest - nums[i], path);
path.remove(path.size() - 1); // 回溯
}
}
}
}
加起来和为目标的值(二)(有重复的元素)
import java.util.*;
public class Solution {
ArrayList<ArrayList<Integer>> ret=new ArrayList<>();
ArrayList<Integer> path = new ArrayList<>();
public ArrayList<ArrayList<Integer>> combinationSum2(int[] num, int target) {
//首先排序
Arrays.sort(num);
dfs(num,0,target,path);
return ret;
}
public void dfs(int []num,int index,int target,ArrayList<Integer> path){
//我们这里做减法,当target为0 返回正确结果
if(target == 0){
ret.add(new ArrayList<>(path));
return;
}
//这里进行循环
for(int i = index; i < num.length; i++){
//进行剪枝,当 num[i]>target的时候 肯定不能继续遍历
if(target - num[i] < 0){
break;
}
//当有相等元素时候,跳过,避免重复
if(i > index && num[i] == num[i-1]){
continue;
}
//代码到这里 已经是有效答案了
path.add(num[i]);
//继续进行递归, 注意这里下标不是 index+1 而是 i+1,
dfs(num, i + 1, target - num[i], path);
//回溯 这里要remove掉
path.remove(path.size()-1);
}
}
}
组合总和(允许重复选择元素的组合) 无重复元素,元素可以使用多次
https://leetcode-cn.com/problems/combination-sum/
给定一个无重复元素的正整数数组 candidates 和一个正整数 target ,找出 candidates 中所有可以使数字和为目标数 target 的唯一组合。candidates 中的数字可以无限制重复被选取。如果至少一个所选数字数量不同,则两种组合是唯一的。
class Solution {
List<List<Integer>> res = new ArrayList<>(); //记录答案
List<Integer> path = new ArrayList<>(); //记录路径
public List<List<Integer>> combinationSum(int[] candidates, int target) {
dfs(candidates, 0, target);
return res;
}
public void dfs(int[] nums, int u, int target) {
if(target < 0) return ;
if(target == 0)
{
res.add(new ArrayList(path));
return ;
}
for(int i = u; i < nums.length; i++){
if( nums[i] <= target)
{
path.add(nums[i]);
dfs(nums, i, target - nums[i]); // 因为可以重复使用,所以还是i
path.remove(path.size() - 1); //回溯,恢复现场
}
}
}
}
含有重复元素的集合(有重复元素,但只能使用一次)
https://leetcode-cn.com/problems/4sjJUc/
给定一个可能有重复数字的整数数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
candidates 中的每个数字在每个组合中只能使用一次,解集不能包含重复的组合。
class Solution {
List<List<Integer>> ret=new ArrayList<>();
List<Integer> path = new ArrayList<>();
public List<List<Integer>> combinationSum2(int[] nums, int target) {
//首先排序
Arrays.sort(nums);
dfs(nums, 0, target, path);
return ret;
}
public void dfs(int[] num, int index, int target, List<Integer> path){
//我们这里做减法,当target为0 返回正确结果
if(target == 0){
ret.add(new ArrayList<>(path));
return;
}
//这里进行循环
for(int i = index; i < num.length; i++){
//进行剪枝,当 num[i]>target的时候 肯定不能继续遍历
if(target - num[i] < 0){
break;
}
//当有相等元素时候,跳过,避免重复
if(i > index && num[i] == num[i-1]){
continue;
}
//代码到这里 已经是有效答案了
path.add(num[i]);
//继续进行递归, 注意这里下标不是 index+1 而是 i+1,
dfs(num, i + 1, target - num[i], path);
//回溯 这里要remove掉
path.remove(path.size()-1);
}
}
}
数字字符串转换成ip地址
import java.util.*;
public class Solution {
ArrayList<String> ret = new ArrayList<>();
ArrayList<String> path = new ArrayList<>();
public ArrayList<String> restoreIpAddresses (String s) {
// write code here
if(s.length() > 12 || s.length() < 4){
return ret;
}
dfs(s, 0, ret, path);
return ret;
}
private void dfs(String s, int depth, List<String> ret, List<String> path){
int n = s.length();
int size = path.size();
if(3 * (4 - size) < n - depth || n - depth < (4 - size)){
// 剩下的分不完了,剪枝
return;
}
if(size == 4 && depth == n){
// 正确的情况
StringBuilder tmp = new StringBuilder();
boolean first = true;
for(String str : path){
if(!first){
tmp.append(".");
}
first = false;
tmp.append(str);
}
ret.add(tmp.toString());
return;
}
// 如果是0需要特判
if(s.charAt(depth) == '0'){
path.add("0");
dfs(s, depth + 1, ret, path);
path.remove(path.size() - 1);
}else{
// 防止越界
int right = Math.min(depth + 3, n);
for(int i = depth; i < right; i++){
String tmp = s.substring(depth, i + 1);
if(check(tmp)){
path.add(tmp);
dfs(s, i + 1, ret, path);
path.remove(path.size() - 1);
}
}
}
}
private boolean check(String s){
int num = Integer.valueOf(s);
return num <= 255 && num >= 0;
}
}
组合
https://leetcode-cn.com/problems/combinations/
class Solution {
List<List<Integer>> ret = new ArrayList<>();
List<Integer> path = new ArrayList<>();
public List<List<Integer>> combine(int n, int k) {
if(k == 0) {
return ret;
}
dfs(n, k, 1);
return ret;
}
//1、递归函数的参数和返回值
public void dfs(int n, int k, int depth){
//2、递归终止条件
if(path.size() == k){
ret.add(new ArrayList<>(path));
return;
}
//3、单层逻辑
for (int i = depth; i <= n; i++) {
path.add(i);
dfs(n, k, i + 1);
//回溯
path.remove(path.size() - 1);
}
}
}
含有k个元素的组合
https://leetcode-cn.com/problems/uUsW3B/
class Solution {
private List<List<Integer>> ret = new ArrayList<>();
private List<Integer> path = new ArrayList<>();
public List<List<Integer>> combine(int n, int k) {
dfs(1, n, k, path);
return ret;
}
private void dfs(int num, int n, int k, List<Integer> path) {
if (k == 0) {
ret.add(new ArrayList<>(path));
return;
}
for (int i = num; i <= n; i++) {
path.add(i);
dfs(i + 1, n, k - 1, path);
path.remove(path.size() - 1);
}
}
}