LeetCode算法题--回溯法

0017电话号码与数字

给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。

package com.Manigoat;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Test0017电话号码的数字组合 {

    static Map<String, String> phone = new HashMap<String, String>() {{
        put("2", "abc");
        put("3", "def");
        put("4", "ghi");
        put("5", "jkl");
        put("6", "mno");
        put("7", "pqrs");
        put("8", "tuv");
        put("9", "wxyz");
    }};
    static List<String>output= new ArrayList<>();

    public static void backtrack(String combination, String next_digits) {
        if (next_digits.length()==0){
            output.add(combination);
            return;
        }else{
            String digit=next_digits.substring(0,1);
            String letters=phone.get(digit);
            for (int i = 0; i < letters.length() ; i++) {
                String letter = letters.substring(i,i+1);
                backtrack(combination+letter,next_digits.substring(1));
            }
        }
    }

    public static List<String> letterCombinations(String digits) {
        output.clear();
        if (digits.length() != 0)
            backtrack("", digits);
        return output;
    }
}

0022括号生成

数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。

public List<String> generateParenthesis(int n) {
    List<String> res = new ArrayList<>();
    // 特判
    if (n == 0) {
        return res;
    }

    // 执行深度优先遍历,搜索可能的结果
    dfs("", n, n, res);
    return res;
}

private void dfs(String curStr, int left, int right, List<String> res) {
    // 因为每一次尝试,都使用新的字符串变量,所以无需回溯
    if (left == 0 && right == 0) {
        res.add(curStr);
        return;
    }

    // 剪枝(如图,左括号可以使用的个数严格大于右括号可以使用的个数,才剪枝,注意这个细节)
    if (left > right||left<0||right<0) {
        return;
    }
    dfs(curStr + "(", left - 1, right, res);
    dfs(curStr + ")", left, right - 1, res);
}

0039组合总和(数字—无数次)

给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。每个数字在每个组合中能使用无数次

public static List<List<Integer>>combineSumList;
public static List<List<Integer>> combinationSum(int[] candidates, int target) {
     combineSumList= new LinkedList<>();
     backtrace(candidates,target,0, new LinkedList<>());
     return combineSumList;
}

public static void backtrace(int candidates[], int target, int start, LinkedList<Integer>list){
    if (target<0){
        return;
    }
    if (target==0){
        combineSumList.add(new LinkedList<>(list));
        return;
    }
    for (int i = start; i < candidates.length ; i++) {
        list.add(candidates[i]);
        backtrace(candidates,target-candidates[i],i,list);
        list.removeLast();
    }
}

0040组合总和(数字—一次)

每个数字在每个组合中只能使用一次,题目输入可以有重复数字,但每个只能用一次

public static List<List<Integer>>combineSum2List;
public static List<List<Integer>> combinationSum2(int[] candidates, int target) {
    Arrays.sort(candidates);
    combineSum2List= new LinkedList<>();
    backtrace(0,candidates,target,new LinkedList<>());
    return combineSum2List;
}

public static void backtrace(int start, int[] candidates, int target, LinkedList<Integer>list){
    if (target<0){
        return;
    }
    if (target==0){
        combineSum2List.add(new LinkedList<>(list));
    }
    for (int i = start; i < candidates.length ; i++) {
        if (i>start&&candidates[i]==candidates[i-1]){
            continue;
        }
        list.add(candidates[i]);
        backtrace(i+1,candidates,target-candidates[i],list);
        list.removeLast();
    }
}

0077组合

给定两个整数 nk,返回 1 … n 中所有可能的 k 个数的组合。

public static List<List<Integer>>combineList;
public static List<List<Integer>> combine(int n, int k) {
    combineList= new LinkedList<>();
    backtrace(n,k,1,new LinkedList<Integer>());
    return combineList;
}
    
public static void backtrace(int n, int k , int start, LinkedList<Integer>list){
    if (list.size()==k){
        combineList.add(new LinkedList<>(list));
        return;
    }
    for (int i = start; i <= n ; i++) {
        list.add(i);
        backtrace(n,k,i+1,list);
        list.removeLast();
    }
}

0046全排列(无重复数字)

static List<List<Integer>>permuteList;
public List<List<Integer>> permute(int[] nums) {
    permuteList= new LinkedList<>();
    int visited[]= new int[nums.length];
    backtrace(nums,new LinkedList<>(),visited);
    return permuteList;
}

public static void backtrace(int nums[], LinkedList<Integer>list, int visited[]){
    if (list.size()==nums.length){
        permuteList.add(new LinkedList<>(list));
        return;
    }
    for (int i = 0; i < nums.length ; i++) {
        if (visited[i]==1){
            continue;
        }
        list.add(nums[i]);
        visited[i]=1;
        backtrace(nums,list,visited);
        list.removeLast();
        visited[i]=0;
    }
}

0047全排列(有重复数字)

//0047
public List<List<Integer>> result = new LinkedList<>();
public List<List<Integer>> permuteUnique(int[] nums) {
    if(nums.length == 0){
        return result;
    }
    //首先给数组排序
    Arrays.sort(nums);
    int[] visited= new int[nums.length];
    findUnique(nums,visited,new LinkedList<Integer>());
    return result;
}
public void findUnique(int[] nums, int[] visited,LinkedList<Integer> trace){
    //结束条件
    if(trace.size() == nums.length){
        result.add(new LinkedList(trace));
        return ;
    }
    //选择列表
    for(int i = 0; i<nums.length; i++){
        //其次,我们已经选择过的不需要再放进去了
        if(visited[i]==1) continue;
        if(i>0 && nums[i] == nums[i-1] && visited[i-1]==0) continue;
        //做出选择
        trace.add(nums[i]);
        visited[i] = 1;
        findUnique(nums,visited,trace);
        //撤销选择
        trace.removeLast();
        visited[i] = 0;
    }
}

0090子集 II

题目:给定一个可能包含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。

说明:解集不能包含重复的子集。

//0090子集
 public static List<List<Integer>>subsetList;
 public static List<List<Integer>> subsetsWithDup(int[] nums) {
     if (nums==null){
         return null;
     }
     Arrays.sort(nums);
     int n=nums.length;
     subsetList= new LinkedList<>();
     for (int i = 0; i <=n ; i++) {
         backtrace(n,i,0,new LinkedList<>(),nums);
     }
     return subsetList;
 }

 public static void backtrace(int n, int k, int start, LinkedList<Integer>list,int nums[]){
     if (list.size()==k){
         subsetList.add(new LinkedList<>(list));
         return;
     }
     for (int i = start; i <= n-1 ; i++) {
         if (i>start&&nums[i-1]==nums[i]){
             continue;
         }
         list.add(nums[i]);
         backtrace(n,k,i+1,list,nums);
         list.removeLast();
     }
 }

0113 路径总和 II

题目:给定一个二叉树和一个目标和,找到所有从根节点到叶子节点路径总和等于给定目标和的路径。

static List<List<Integer>>pathSumList;
public static List<List<Integer>> pathSum(TreeNode root, int sum) {
    pathSumList= new LinkedList<>();
    backtrace(root, sum, new LinkedList<>());
    return pathSumList;
}

public static void backtrace(TreeNode root,int sum, LinkedList<Integer>list){
    if (root==null){
        return;
    }
    list.add(root.val);
    sum-=root.val;
    if (sum==0&&root.left==null&&root.right==null){
        pathSumList.add(new LinkedList<>(list));
    }
    backtrace(root.left, sum, list);
    backtrace(root.right, sum,list);
    list.removeLast();
}
原创文章 14 获赞 10 访问量 579

猜你喜欢

转载自blog.csdn.net/qq_43672466/article/details/105746778