Leetcode回溯

2020-10-09  本文已影响0人  1nvad3r

17. 电话号码的字母组合

class Solution {
    List<String> res = new ArrayList<>();
    StringBuilder temp = new StringBuilder();
    String[] map = {"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};

    void dfs(int index, String digits) {
        if (index == digits.length()) {
            res.add(temp.toString());
            return;
        }
        int num = digits.charAt(index) - '0';
        for (int i = 0; i < map[num].length(); i++) {
            temp.append(map[num].charAt(i));
            dfs(index + 1, digits);
            temp.deleteCharAt(temp.length() - 1);
        }
    }

    public List<String> letterCombinations(String digits) {
        if ("".equals(digits)) {
            return new ArrayList<>();
        }
        dfs(0, digits);
        return res;
    }
}

22. 括号生成

class Solution {
    List<String> res = new ArrayList<>();
    StringBuilder temp = new StringBuilder();

    void dfs(int index, int left, int right, int n) {
        //剪枝
        if (left == n + 1 || right > left) {
            return;
        }
        if (index == 2 * n) {
            res.add(temp.toString());
            return;
        }
        temp.append("(");
        dfs(index + 1, left + 1, right, n);
        temp.deleteCharAt(temp.length() - 1);
        temp.append(")");
        dfs(index + 1, left, right + 1, n);
        temp.deleteCharAt(temp.length() - 1);
    }

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

37. 解数独

class Solution {
    public boolean dfs(char[][] board) {
        for (int i = 0; i < board.length; i++) {
            for (int j = 0; j < board.length; j++) {
                if (board[i][j] == '.') {
                    for (char c = '1'; c <= '9'; c++) {
                        if (isValid(i, j, c, board) == true) {
                            board[i][j] = c;
                            if (dfs(board) == true) {
                                return true;
                            } else {
                                board[i][j] = '.';
                            }
                        }
                    }
                    return false;
                }
            }
        }
        return true;
    }

    boolean isValid(int row, int col, char c, char[][] board) {
        int blockRow = 3 * (row / 3);
        int blockCol = 3 * (col / 3);
        for (int i = 0; i < 9; i++) {
            if (board[i][col] == c) {
                return false;
            }
            if (board[row][i] == c) {
                return false;
            }
            if (board[blockRow + i / 3][blockCol + i % 3] == c) {
                return false;
            }
        }
        return true;
    }

    public void solveSudoku(char[][] board) {
        dfs(board);
    }
}

39. 组合总和

组合问题,使用index防止重复。

class Solution {
    List<List<Integer>> res = new ArrayList<>();
    List<Integer> temp = new ArrayList<>();

    void dfs(int index, int sum, int target, int[] candidates) {
        if (sum > target) {
            return;
        }
        if (sum == target) {
            res.add(new ArrayList<>(temp));
        }
        for (int i = index; i < candidates.length; i++) {
            temp.add(candidates[i]);
            dfs(i, sum + candidates[i], target, candidates);
            temp.remove(temp.size() - 1);
        }
    }

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

40. 组合总和 II

class Solution {
    List<List<Integer>> res = new ArrayList<>();
    List<Integer> temp = new ArrayList<>();

    void dfs(int index, int sum, int target, int[] candidates) {
        if (index > candidates.length || sum > target) {
            return;
        }
        if (sum == target) {
            res.add(new ArrayList<>(temp));
            return;
        }
        for (int i = index; i < candidates.length; i++) {
            if (i - 1 >= index && candidates[i] == candidates[i - 1]) {
                continue;
            }
            temp.add(candidates[i]);
            dfs(i + 1, sum + candidates[i], target, candidates);
            temp.remove(temp.size() - 1);
        }
    }

    public List<List<Integer>> combinationSum2(int[] candidates, int target) {
        Arrays.sort(candidates);
        dfs(0, 0, target, candidates);
        return res;
    }
}

46. 全排列

排列问题使用isVisit数组标记某个元素是否已访问。

class Solution {
    List<List<Integer>> res = new ArrayList<>();
    List<Integer> temp = new ArrayList<>();
    boolean[] isVisit;

    void dfs(int index, int[] nums) {
        if (index == nums.length) {
            res.add(new ArrayList<>(temp));
            return;
        }
        for (int i = 0; i < nums.length; i++) {
            if (isVisit[i] == false) {
                isVisit[i] = true;
                temp.add(nums[i]);
                dfs(index + 1, nums);
                temp.remove(temp.size() - 1);
                isVisit[i] = false;
            }
        }
    }

    public List<List<Integer>> permute(int[] nums) {
        isVisit = new boolean[nums.length];
        dfs(0, nums);
        return res;
    }
}

47. 全排列 II

class Solution {
    List<List<Integer>> res = new ArrayList<>();
    List<Integer> temp = new ArrayList<>();
    boolean[] isVisit;

    void dfs(int[] nums) {
        if (temp.size() == nums.length) {
            res.add(new ArrayList<>(temp));
            return;
        }
        for (int i = 0; i < nums.length; i++) {
            //isVisit[i - 1] == false时说明到达同一层相同的地方
            if (i - 1 >= 0 && nums[i] == nums[i - 1] && isVisit[i - 1] == false) {
                continue;
            }
            if (isVisit[i] == false) {
                isVisit[i] = true;
                temp.add(nums[i]);
                dfs(nums);
                temp.remove(temp.size() - 1);
                isVisit[i] = false;
            }
        }
    }

    public List<List<Integer>> permuteUnique(int[] nums) {
        isVisit = new boolean[nums.length];
        Arrays.sort(nums);
        dfs(nums);
        return res;
    }
}

51. N 皇后

class Solution {
    List<List<String>> res = new ArrayList<>();
    boolean[] isVisit;
    int[] arr;

    boolean judge(int n) {
        boolean flag = true;
        boolean flag2 = true;//使用标记快速跳出双重for循环
        for (int i = 1; i <= n; i++) {
            for (int j = i + 1; j <= n; j++) {
                if (Math.abs(i - j) == Math.abs(arr[i] - arr[j])) {//在对角线上
                    flag = false;
                    flag2 = false;
                    break;
                }
            }
            if (flag2 == false) {
                break;
            }
        }
        return flag;
    }

    void dfs(int index, int n) {
        if (index == n + 1) {
            if (judge(n) == true) {
                List<String> list = new ArrayList<>();
                for (int i = 1; i <= n; i++) {
                    int col = arr[i];
                    StringBuilder sb = new StringBuilder();
                    for (int j = 1; j <= n; j++) {
                        if (j != col) {
                            sb.append(".");
                        } else {
                            sb.append("Q");
                        }
                    }
                    list.add(sb.toString());
                }
                res.add(list);
            }
            return;
        }
        for (int i = 1; i <= n; i++) {
            if (isVisit[i] == false) {
                arr[index] = i;
                isVisit[i] = true;
                dfs(index + 1, n);
                isVisit[i] = false;
            }
        }
    }

    public List<List<String>> solveNQueens(int n) {
        isVisit = new boolean[n + 1];
        arr = new int[n + 1];
        dfs(1, n);
        return res;
    }
}

52. N皇后 II

class Solution {
    int res = 0;
    boolean[] isVisit;
    int[] arr;

    boolean judge(int n) {
        boolean flag = true;
        boolean flag2 = true;
        for (int i = 1; i <= n; i++) {
            for (int j = i + 1; j <= n; j++) {
                if (Math.abs(i - j) == Math.abs(arr[i] - arr[j])) {//在对角线上
                    flag = false;
                    flag2 = false;
                    break;
                }
            }
            if (flag2 == false) {
                break;
            }
        }
        return flag;
    }

    void dfs(int index, int n) {
        if (index == n + 1) {
            if (judge(n) == true) {
                res++;
            }
            return;
        }
        for (int i = 1; i <= n; i++) {
            if (isVisit[i] == false) {
                arr[index] = i;
                isVisit[i] = true;
                dfs(index + 1, n);
                isVisit[i] = false;
            }
        }
    }

    public int totalNQueens(int n) {
        isVisit = new boolean[n + 1];
        arr = new int[n + 1];
        dfs(1, n);
        return res;
    }
}

60. 第k个排列

class Solution {
    boolean[] isVisit;
    StringBuilder res;
    StringBuilder temp = new StringBuilder();
    int count = 0;

    void dfs(int index, int n, int k) {

        if (index == n + 1) {
            count++;
            if (count == k) {
                res = new StringBuilder(temp);
            }
            return;
        }

        for (int i = 1; i <= n; i++) {
            if (isVisit[i] == false) {
                temp.append(i);
                isVisit[i] = true;
                dfs(index + 1, n, k);
                isVisit[i] = false;
                temp.deleteCharAt(temp.length() - 1);
            }
        }
    }

    public String getPermutation(int n, int k) {
        isVisit = new boolean[n + 1];
        dfs(1, n, k);
        return res.toString();
    }
}

77. 组合

class Solution {
    List<List<Integer>> res = new ArrayList<>();
    List<Integer> temp = new ArrayList<>();

    void dfs(int index, int n, int k) {
        if (temp.size() == k) {
            res.add(new ArrayList<>(temp));
            return;
        }
        for (int i = index; i <= n; i++) {
            temp.add(i);
            dfs(i + 1, n, k);
            temp.remove(temp.size() - 1);
        }
    }

    public List<List<Integer>> combine(int n, int k) {
        dfs(1, n, k);
        return res;
    }
}

78. 子集

可以使用选与不选的dfs。
也可以使用在递归的过程中就把temp加入到res中。

class Solution {
    List<List<Integer>> res = new ArrayList<>();
    List<Integer> temp = new ArrayList<>();

    void dfs(int index, int[] nums) {
        if (index == nums.length) {
            res.add(new ArrayList<>(temp));
            return;
        }
        temp.add(nums[index]);
        dfs(index + 1, nums);
        temp.remove(temp.size() - 1);
        dfs(index + 1, nums);
    }

    public List<List<Integer>> subsets(int[] nums) {
        dfs(0, nums);
        return res;
    }
}
class Solution {
    List<List<Integer>> res = new ArrayList<>();
    List<Integer> temp = new ArrayList<>();

    void dfs(int index, int[] nums) {
        if (index == nums.length) {
            return;
        }
        for (int i = index; i < nums.length; i++) {
            temp.add(nums[i]);
            res.add(new ArrayList<>(temp));
            dfs(i + 1, nums);
            temp.remove(temp.size() - 1);
        }
    }

    public List<List<Integer>> subsets(int[] nums) {
        dfs(0, nums);
        res.add(new ArrayList<>());
        return res;
    }
}

79. 单词搜索

class Solution {

    boolean[][] isVisit;
    int[] X = {0, 0, -1, 1};//上下左右
    int[] Y = {-1, 1, 0, 0};

    //对所有规则进行判断
    boolean check(char[][] board, int i, int j, int k, String word) {
        if (i < 0 || i >= board.length || j < 0 || j >= board[0].length) {
            return false;
        }
        if (isVisit[i][j] == true) {
            return false;
        }
        if (board[i][j] == word.charAt(k)) {
            return true;
        } else {
            return false;
        }
    }


    boolean dfs(char[][] board, int i, int j, int k, String word) {
        if (k == word.length()) {
            return true;
        }
        if (check(board, i, j, k, word) == true) {
            isVisit[i][j] = true;
            for (int z = 0; z < 4; z++) {
                int newI = i + X[z];
                int newJ = j + Y[z];
                if (dfs(board, newI, newJ, k + 1, word) == true) {
                    return true;
                }
            }
            //如果某一点四个方向都不满足条件,改回false
            isVisit[i][j] = false;
        } else {
            return false;
        }
        return false;
    }

    public boolean exist(char[][] board, String word) {
        isVisit = new boolean[board.length][board[0].length];
        //从每一个字母开始出发进行DFS
        for (int i = 0; i < board.length; i++) {
            for (int j = 0; j < board[0].length; j++) {
                boolean res = dfs(board, i, j, 0, word);
                if (res == true) {
                    return true;
                } else {
                    continue;
                }
            }
        }
        return false;
    }
}

89. 格雷编码

class Solution {
    public List<Integer> grayCode(int n) {
        List<Integer> res = new ArrayList<>();
        res.add(0);
        int head = 1;
        for (int i = 1; i <= n; i++) {
            for (int j = res.size() - 1; j >= 0; j--) {
                res.add(res.get(j) + head);
            }
            head <<= 1;
        }
        return res;
    }
}

90. 子集 II

class Solution {
    List<List<Integer>> res = new ArrayList<>();
    List<Integer> temp = new ArrayList<>();

    void dfs(int index, int[] nums) {
        if (index == nums.length) {
            return;
        }
        for (int i = index; i < nums.length; i++) {
            if (i - 1 >= index && nums[i] == nums[i - 1]) {
                continue;
            }
            temp.add(nums[i]);
            res.add(new ArrayList<>(temp));
            dfs(i + 1, nums);
            temp.remove(temp.size() - 1);
        }
    }

    public List<List<Integer>> subsetsWithDup(int[] nums) {
        Arrays.sort(nums);
        res.add(new ArrayList<>());
        dfs(0, nums);
        return res;
    }
}

93. 复原IP地址

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

    void dfs(int index, String s) {
        if (index == s.length() && segment.size() == 4) {
            StringBuilder t = new StringBuilder();
            for (String se : segment) t.append(se).append(".");
            t.deleteCharAt(t.length() - 1);
            res.add(t.toString());
            return;
        }
        if (index < s.length() && segment.size() == 4) {
            return;
        }

        for (int i = 1; i <= 3; i++) {
            if (index + i > s.length()) {
                return;
            }
            if (i != 1 && s.charAt(index) == '0') {
                return;
            }
            String str = s.substring(index, index + i);
            if (i == 3 && Integer.parseInt(str) > 255) {
                return;
            }
            segment.add(str);
            dfs(index + i, s);
            segment.remove(segment.size() - 1);
        }
    }

    public List<String> restoreIpAddresses(String s) {
        dfs(0, s);
        return res;
    }
}

131. 分割回文串

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

    boolean isPalindromic(String s) {
        for (int i = 0; i < s.length() / 2; i++) {
            if (s.charAt(i) != s.charAt(s.length() - 1 - i)) {
                return false;
            }
        }
        return true;
    }

    void dfs(int index, String s) {
        if (index == s.length()) {
            res.add(new ArrayList<>(temp));
            return;
        }
        for (int i = index; i < s.length(); i++) {
            String str = s.substring(index, i + 1);
            if (isPalindromic(str) == true) {
                temp.add(str);
                dfs(i + 1, s);
                temp.remove(temp.size() - 1);
            }
        }
    }

    public List<List<String>> partition(String s) {
        dfs(0, s);
        return res;
    }
}

132. 分割回文串 II

超时了,思路是正确的。
待优化成动态规划做。

class Solution {
    int res = Integer.MAX_VALUE;
    List<String> temp = new ArrayList<>();

    public boolean isPar(String s) {
        int i = 0, j = s.length() - 1;
        while (i < j) {
            if (s.charAt(i) != s.charAt(j)) {
                return false;
            }
            i++;
            j--;
        }
        return true;
    }

    public void dfs(int begin, String s) {
        if (begin == s.length()) {
            res = Math.min(res, temp.size() - 1);
        }
        for (int i = begin; i < s.length(); i++) {
            String sub = s.substring(begin, i + 1);
            if (isPar(sub) == true) {
                temp.add(sub);
                dfs(i + 1, s);
                temp.remove(temp.size() - 1);
            }
        }
    }

    public int minCut(String s) {
        dfs(0, s);
        return res;
    }
}
上一篇下一篇

猜你喜欢

热点阅读