hot100-一刷-10回溯(共8道题)

46. 全排列

题目链接

题目描述

image

代码实现

分析:

代码:

class Solution {
    List<List<Integer>> ans = new ArrayList<>();
    List<Integer> path = new ArrayList<>();

    public List<List<Integer>> permute(int[] nums) {
        backTracing(nums, new boolean[nums.length]);
        return ans;
    }

    private void backTracing(int[] nums, boolean[] used){
        if(path.size() == nums.length){
            ans.add(new ArrayList(path));
            return;
        }
        for(int i = 0; i < nums.length; i++){
            if (used[i]) continue;
            path.add(nums[i]);
            used[i] = true;
            backTracing(nums, used);
            used[i] = false;
            path.remove(path.size() - 1);
        }
    }
}

78. 子集

题目链接

题目描述

image

代码实现

分析:

代码:

class Solution {
    List<List<Integer>> ans = new ArrayList<>();
    List<Integer> path = new ArrayList<>();

    public List<List<Integer>> subsets(int[] nums) {
        backTracing(nums, 0);
        return ans;
    }

    private void backTracing(int[] nums, int startIdx){
        ans.add(new ArrayList(path));
        // 加不加都行, 因为递归是在for循环里,startIdx>=nums.length的时候, 不走for,直接返回
        // if(startIdx >= nums.length) return;
        for (int i = startIdx; i < nums.length; i++){
            path.add(nums[i]);
            backTracing(nums, i+1);
            path.remove(path.size() - 1);
        }
    }
}

// 从输入的角度,选或者不选
class Solution {
    List<List<Integer>> ans = new ArrayList<>();
    List<Integer> path = new ArrayList<>();

    public List<List<Integer>> subsets(int[] nums) {
        dfs(nums, 0);
        return ans;
    }

    private void dfs(int[] nums, int i){
        if(i == nums.length){
            ans.add(new ArrayList(path));
            return;
        }
        // 每次遍历当前index时,分两个情况, 选或者不选
        // 不选, 也就是不向path记录这个数据
        dfs(nums, i+1);

        // 选, 向path记录这个数据
        path.add(nums[i]);
        dfs(nums, i+1);
        // 返回时要复原现场,恢复到没选的样子。
        path.remove(path.size() - 1);
    }
}

17. 电话号码的字母组合

题目链接

题目描述

image

代码实现

分析:

代码:

class Solution {
    private static final String[] MAP = new String[]{
            "","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"
    };

    List<String> ans = new ArrayList<>();
    StringBuilder sb = new StringBuilder();

    public List<String> letterCombinations(String digits) {
        if (digits == null || digits.length() == 0) return ans;
        backTracing(digits, 0);
        return ans;
    }

    private void backTracing(String digits, int idxInDigits){
        if(sb.length() == digits.length()){
            ans.add(sb.toString());
            return;
        }
        // 计算index位置的整型
        int idx = digits.charAt(idxInDigits)-'0';
        // MAP中对应位置元素的个数 
        int len = MAP[idx].length();
        for (int i = 0; i < len; i++){
            sb.append(MAP[idx].charAt(i));
            backTracing(digits, idxInDigits+1);
            sb.deleteCharAt(sb.length()-1);
        }
    }
}

39. 组合总和

题目链接

题目描述

image

代码实现

分析:

代码:

class Solution {
    List<List<Integer>> ans = new ArrayList<>();
    List<Integer> path = new ArrayList<>();

    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        backTracing(candidates, target, 0);
        return ans;
    }

    private void backTracing(int[] candidates, int target, int startIdx){
        if(0 == target){
            ans.add(new ArrayList(path));
            return;
        }
        if(target<0) return;

        for (int i = startIdx; i < candidates.length; i++){
            if(target < candidates[i]) continue;
            path.add(candidates[i]);
            backTracing(candidates, target- candidates[i], i);
            path.remove(path.size() - 1);
        }
    }
}

class Solution {
    List<List<Integer>> ans = new ArrayList<>();
    List<Integer> path = new ArrayList<>();

    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        dfs(candidates, target, 0);
        return ans;
    }

    private void dfs(int[] candidates, int target, int i){
        if(target == 0) {
            ans.add(new ArrayList(path));
            return;
        }
        
        if(i == candidates.length || target < 0){
            return;
        }

        // 不选 下标加1
        dfs(candidates, target, i+1);

        // 选  目标改变, 下标不变 -> 可以再取同一个数
        path.add(candidates[i]);
        dfs(candidates, target - candidates[i], i);
        path.remove(path.size() - 1);
    }
}

22. 括号生成

题目链接

题目描述

image

代码实现

分析:

  • 选或不选

代码:

class Solution {
    private int n;
    private List<String> ans = new ArrayList<>();
    private char[] path;

    public List<String> generateParenthesis(int n) {
        this.n = n;
        path = new char[n*2];
        dfs(0, 0);
        return ans;
    }

    private void dfs(int i, int open){
        // 字符总数达到了n对括号
        if (i == n * 2){
            ans.add(new String(path));
            return;
        } 

        // 左括号的个数小于n,可以加左括号
        if (open < n) {
            path[i] = '('; // 第i个位置左括号
            dfs(i+1, open+1); // 左括号个数更新
        }

        // 左括号的个数比右括号多, 才可以加右括号
        if (open > i - open) {
            path[i] = ')';
            dfs(i+1, open);
        }        
    }
}

79. 单词搜索

题目链接

题目描述

image

代码实现

分析:

  • dfs + 回溯

代码:

class Solution {

    private static final int[][] DIRS = {{0, -1}, {0, 1}, {-1, 0}, {1, 0}};

    public boolean exist(char[][] board, String word) {
        for (int i = 0; i < board.length; i++){
            for (int j = 0; j < board[0].length; j++){
                if(dfs(i, j, 0, board, word.toCharArray()))
                    return true;
            }
        }
        return false;
    }

    private boolean dfs(int i, int j, int k, char[][] board, char[] word){
        if (board[i][j] != word[k]){
            return false;
        }

        if(k == word.length -1){
            return true;
        }

        board[i][j] = 0;  // 标记已经走过的
        for (int[] d : DIRS){
            int x = i + d[0];
            int y = j + d[1];
            if (x >= 0 && x < board.length && y >= 0 && y < board[0].length && dfs(x, y, k+1, board, word)){
                return true;
            }
        }
        board[i][j] = word[k];  // 回溯
        return false;

    }
}

131. 分割回文串

题目链接

题目描述

image

代码实现

分析:

代码:

class Solution {
    List<List<String>> ans = new ArrayList<>();
    List<String> path = new ArrayList<>();
    private String s;

    public List<List<String>> partition(String s) {
        this.s = s;
        dfs(0);
        return ans;
    }

    private void dfs(int i){
        if(i == s.length()){
            ans.add(new ArrayList(path));
            return;
        }

        for (int j = i; j < s.length(); j++){
            if(isPalindrome(i, j)){
                path.add(s.substring(i, j+1));
                dfs(j+1);
                path.remove(path.size()-1);
            }
        }
    }

    private boolean isPalindrome(int left, int right){
        while(left < right){
            if(s.charAt(left++) != s.charAt(right--)){
                return false;
            }
        }
        return true;
    }
}


51. N 皇后

题目链接

题目描述

image

代码实现

分析:

代码:

class Solution {
    List<List<String>> ans = new ArrayList<>();

    public List<List<String>> solveNQueens(int n) {
        char[][] chessboard = new char[n][n];
        for(char[] c : chessboard){
            Arrays.fill(c, '.');
        }
        backTracing(n, 0, chessboard);
        return ans;
    }

    private void backTracing(int n, int row, char[][] chessboard){
        if(n == row){
            ans.add(charArr2List(chessboard));
            return;
        }

        for (int i = 0; i < n; i++){
            if(isValid(row, i, n, chessboard)){
                chessboard[row][i] = 'Q';
                backTracing(n, row + 1, chessboard);
                chessboard[row][i] = '.';
            }
        }

    }

    private boolean isValid(int row, int col, int n, char[][] chessboard){
        // 列
        for (int i = 0; i < row; i++){
            if (chessboard[i][col] == 'Q')
                return false;
        }

        // 检查左上角
        for(int i = row-1, j = col-1; i >=0 && j>=0; i--,j--){
            if(chessboard[i][j] == 'Q')
                return false;
        }


        // 检查右上角
        for(int i = row-1, j = col+1; i >=0 && j<n; i--,j++){
            if(chessboard[i][j] == 'Q')
                return false;
        }
        return true;
    }

    private List<String> charArr2List(char[][] chessboard){
        List<String> path = new ArrayList<>();
        for(char[] c : chessboard){
            path.add(new String(c));
        }
        return path;
    }
}
posted @ 2024-12-17 22:59  chendsome  阅读(6)  评论(0编辑  收藏  举报