hot100 | 十、回溯

1-leetcode46. 全排列

注意:×

  1. 看了两遍以后还是犯了错误:在将trace赋值给res的时候,一定要注意是新创建一个数组而不是直接将数组给进去,直接给的话是浅拷贝,最后会全是[]
  2. 接下来是注意的地方,要注意回溯的函数是包含nums, trace, used
  3. 用的是LinkedList因为需要频繁的对数组的最后进行删减
    List<List<Integer>> res = new LinkedList<>();
    public List<List<Integer>> permute(int[] nums) {
        boolean[] used = new boolean[nums.length];
        LinkedList<Integer> trace = new LinkedList<>();
        backtrace(nums, trace, used);
        return res;
    }

    private void backtrace(int[] nums, LinkedList<Integer> trace, boolean[] used) {
        if (trace.size() == nums.length){
            res.add(new LinkedList<>(trace));
            return;
        }
        for (int i = 0; i < nums.length; i++) {
            if (used[i]){
                continue;
            }
            used[i] = true;
            trace.add(nums[i]);
            backtrace(nums, trace, used);
            trace.removeLast();
            used[i] = false;
        }
    }

2-leetcode78. 子集

注意:×

  1. 非常好的看完题解一趟过,注意子集问题中的回溯需要nums, 0
    List<List<Integer>> res = new LinkedList<>();
    LinkedList<Integer> trace = new LinkedList<>();
    public List<List<Integer>> subsets(int[] nums) {
        backtrace(nums, 0);
        return res;
    }

    private void backtrace(int[] nums, int start) {
        res.add(new LinkedList<>(trace));

        for (int i = start; i< nums.length; i++){
            trace.add(nums[i]);
            backtrace(nums, i+1);
            trace.removeLast();
        }
    }

3-leetcode17. 电话号码的字母组合

注意:×

  1. String[]的写法
  2. StringBuild的使用
  3. 主要还是backtrace里面的对digits的下标控制
    List<String> res = new LinkedList<>();
    StringBuilder sb = new StringBuilder();
    String[] map = new String[]{"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};

    public List<String> letterCombinations(String digits) {
        if (digits.isEmpty()){
            return res;
        }

        backtrace(digits, 0);
        return res;
    }

    private void backtrace(String digits, int start) {
        if (sb.length() == digits.length()){
            res.add(sb.toString());
            return;
        }

        int index = digits.charAt(start) - '0';
        for (char c : map[index].toCharArray()){
            sb.append(c);
            backtrace(digits, start+1);
            sb.deleteCharAt(sb.length()-1);
        }
    }

4-leetcode39. 组合总和

注意:×

  1. 看完题解一趟过
  2. 核心是对重复使用的处理,主要就是for循环的时候递归仍然从当前位置进行查找
  3. 然后是加入res的逻辑和终止条件
    private  List<List<Integer>> res =  new LinkedList<>();
    private  LinkedList<Integer> track =  new LinkedList<>();
    private int trackSum = 0;

    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        if (candidates.length == 0){
            return res;
        }
        backtrack(candidates, 0, target);
        return res;
    }

    private void backtrack(int[] candidates, int start, int target) {
        if (trackSum == target){
            res.add(new LinkedList<>(track));
            return;
        }
        if (trackSum > target){
            return;
        }

        for(int i = start; i< candidates.length; i++){
            trackSum = trackSum + candidates[i];
            track.add(candidates[i]);

            backtrack(candidates, i, target);

            track.removeLast();
            trackSum = trackSum - candidates[i];
        }
    }

5-leetcode22. 括号生成

注意:×

  1. Labuladong非常非常强的思路
  2. 和之前一样的回溯框架,但是传的是用 left 记录还可以使用多少个左括号,用 right 记录还可以使用多少个右括号
    来源Labuladong
    private List<String> res = new LinkedList<>();
    private StringBuilder sb = new StringBuilder();

    public List<String> generateParenthesis(int n) {
        if (n == 0){
            return res;
        }
        backtrack(n, n);
        return res;
    }

    private void backtrack(int left, int right) {
        if (left > right){
            return;
        }
        if (left<0 || right<0){
            return;
        }
        if (left == 0 && right == 0){
            res.add(sb.toString());
            return;
        }

        sb.append('(');
        backtrack(left-1, right);
        sb.deleteCharAt(sb.length()-1);

        sb.append(')');
        backtrack(left, right-1);
        sb.deleteCharAt(sb.length()-1);
    }

6-leetcode79. 单词搜索

注意:×

  1. 类似岛屿问题的回溯方法,注意需要在四联之前标记已经走过,四联以后取消标记
  2. backtrack里面的一系列判断
  3. 一定一定要注意对i,j的下标判断!!!!!!!!!!!!!!!!!!!
  4. 已经不知道第几次错了,这个下标要注意m跟n那一边,是>=<=
    private boolean isExist = false;
    public boolean exist(char[][] board, String word) {
        int n = board.length;
        int m = board[0].length;
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                backtrack(board, i, j, word, 0);
                if (isExist){
                    return true;
                }
            }
        }
        return false;
    }

    private void backtrack(char[][] board, int i, int j, String word, int index) {
        if (isExist){
            return;
        }
        if (index == word.length()){
            isExist = true;
            return;
        }
        int n = board.length;
        int m = board[0].length;
        if (i<0 || j<0 || i>=n || j>=m){
            return;
        }
        if (board[i][j] != word.charAt(index)){
            return;
        }

        board[i][j] = (char) -board[i][j];
        backtrack(board, i+1, j, word, index+1);
        backtrack(board, i, j+1, word, index+1);
        backtrack(board, i-1, j, word, index+1);
        backtrack(board, i, j-1, word, index+1);
        board[i][j] = (char) -board[i][j];
    }

7-leetcode131. 分割回文串

注意:×√

  1. 看完题解手搓出来的
  2. 注意substring操作
    List<List<String>> res = new LinkedList<>();
    LinkedList<String> track = new LinkedList<>();
    public List<List<String>> partition(String s) {
        if (s.length() == 0){
            return res;
        }
        backtrack(s, 0);
        return res;
    }

    private void backtrack(String s, int index) {
        if (index == s.length()){
            res.add(new LinkedList<>(track));
            return;
        }
        for (int i = index; i < s.length(); i++) {
            if (!checkIsHuiWen(s, index, i)){
                continue;
            }
            track.add(s.substring(index, i+1));
            backtrack(s, i+1);
            track.removeLast();
        }

    }

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

8-leetcode51. N 皇后

注意:×

  1. 垃圾玩意,不写也罢

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值