日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

LeetCode——Backtracking

發布時間:2024/2/28 编程问答 1434 豆豆
生活随笔 收集整理的這篇文章主要介紹了 LeetCode——Backtracking 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Backtracking


目錄

  • Backtracking
  • 數字鍵盤組合
  • IP 地址劃分
  • 在矩陣中尋找字符串
  • 輸出二叉樹中所有從根到葉子的路徑
  • 排列
  • 含有相同元素求排列
  • 組合
  • 組合求和
  • 含有相同元素的組合求和
  • 1-9 數字的組合求和
  • 子集
  • 含有相同元素求子集
  • 分割字符串使得每個部分都是回文數
  • 數獨
  • N皇后

  • 1. Backtracking

    Backtracking(回溯)屬于 DFS。
    普通 DFS 主要用在可達性問題,這種問題只需要執行到特點的位置然后返回即可。

    而 Backtracking 主要用于求解 排列組合 問題,例如有 { ‘a’,‘b’,‘c’ } 三個字符,求解所有由這三個字符排列得到的字符串,這種問題在執行到特定的位置返回之后還會繼續執行求解過程。

    因為 Backtracking 不是立即返回,而要繼續求解,因此在程序實現時,需要注意對元素的標記問題:
    在訪問一個新元素進入新的遞歸調用時,需要將新元素標記為已經訪問,這樣才能在繼續遞歸調用時不用重復訪問該元素;

    但是在遞歸返回時,需要將元素標記為未訪問,因為只需要保證在一個遞歸鏈中不同時訪問一個元素,可以訪問已經訪問過但是不在當前遞歸鏈中的元素。


    2. 數字鍵盤組合

    https://leetcode-cn.com/problems/letter-combinations-of-a-phone-number

    private static final String[] KEYS = {"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};public List<String> letterCombinations(String digits){List<String> combinations = new ArrayList<>();if (digits==null||digits.length()==0){return combinations;}doCombination(new StringBuilder(),combinations,digits);return combinations;}private void doCombination(StringBuilder prefix, List<String> combinations, final String digits) {if (prefix.length()==digits.length()){combinations.add(prefix.toString());return;}int num = digits.charAt(prefix.length()) - '0';String key = KEYS[num];for (char c : key.toCharArray()) {prefix.append(c);doCombination(prefix,combinations,digits);prefix.deleteCharAt(prefix.length()-1);}}

    3. IP 地址劃分

    https://leetcode-cn.com/problems/restore-ip-addresses

    public List<String> restoreIpAddresses(String s) {List<String> addresses = new ArrayList<>();StringBuilder tempAddress = new StringBuilder();doRestore(0, tempAddress, addresses, s);return addresses;}private void doRestore(int k, StringBuilder tempAddress, List<String> addresses, String s) {//整體分成4個段if (k == 4 || s.length() == 0) {if (k == 4 && s.length() == 0) {addresses.add(tempAddress.toString());}return;}//每個段的判斷for (int i = 0; i < s.length() && i <= 2; i++) {if (i != 0 && s.charAt(0) == '0') {break;}String part = s.substring(0, i + 1);if (Integer.valueOf(part) <= 255) {if (tempAddress.length() != 0) {part = "." + part;}tempAddress.append(part);doRestore(k + 1, tempAddress, addresses, s.substring(i + 1));tempAddress.delete(tempAddress.length() - part.length(), tempAddress.length());}}}

    4. 在矩陣中尋找字符串

    https://leetcode-cn.com/problems/word-search


    題目描述:給定一個二維網格和一個單詞,找出該單詞是否存在于網格中。

    單詞必須按照字母順序,通過相鄰的單元格內的字母構成,其中“相鄰”單元格是那些水平相鄰或垂直相鄰的單元格。同一個單元格內的字母不允許被重復使用。

    private final static int[][] direction = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};private int m, n;public boolean exist(char[][] board, String word) {if (word == null || word.length() == 0) {return true;}if (board == null || board.length == 0 || board[0].length == 0) {return false;}m = board.length;n = board[0].length;boolean[][] visited = new boolean[m][n];for (int r = 0; r < m; r++) {for (int c = 0; c < n; c++) {if (backtracking(0, r, c, visited, board, word)) {return true;}}}return false;}private boolean backtracking(int curLen, int r, int c, boolean[][] visited, final char[][] board, final String word) {if (curLen == word.length()) {return true;}if (r < 0 || r >= m || c < 0 || c >= n || board[r][c] != word.charAt(curLen) || visited[r][c]) {return false;}visited[r][c] = true;for (int[] d : direction) {if (backtracking(curLen + 1, r + d[0], c + d[1], visited, board, word)) {return true;}}visited[r][c] = false;return false;}

    5. 輸出二叉樹中所有從根到葉子的路徑

    https://leetcode.com/problems/binary-tree-paths

    public static class TreeNode {int val = 0;TreeNode left = null;TreeNode right = null;public TreeNode(int val) {this.val = val;}}public List<String> binaryTreePaths(TreeNode root) {List<String> paths = new ArrayList<>();if (root == null) {return paths;}List<Integer> values = new ArrayList<>();backtracking(root, values, paths);return paths;}private void backtracking(TreeNode node, List<Integer> values, List<String> paths) {if (node == null) {return;}values.add(node.val);if (isLeaf(node)) {paths.add(buildPath(values));} else {backtracking(node.left, values, paths);backtracking(node.right, values, paths);}values.remove(values.size() - 1);}private String buildPath(List<Integer> values) {StringBuilder str = new StringBuilder();for (int i = 0; i < values.size(); i++) {str.append(values.get(i));if (i != values.size() - 1) {str.append("->");}}return str.toString();}private boolean isLeaf(TreeNode node) {return node.left == null && node.right == null;}

    6. 排列


    題目描述:給定一個沒有重復數字的序列,返回其所有可能的全排列。

    public List<List<Integer>> permute(int[] nums) {List<List<Integer>> permutes = new ArrayList<>();List<Integer> permuteList = new ArrayList<>();boolean[] hasVisited = new boolean[nums.length];backtracking(permuteList, permutes, hasVisited, nums);return permutes;}private void backtracking(List<Integer> permuteList, List<List<Integer>> permutes, boolean[] visited, int[] nums) {if (permuteList.size() == nums.length) {permutes.add(new ArrayList<>(permuteList)); //重新構造一個 Listreturn;}for (int i = 0; i < visited.length; i++) {if (visited[i]) {continue;}visited[i] = true;permuteList.add(nums[i]);backtracking(permuteList, permutes, visited, nums);permuteList.remove(permuteList.size() - 1);visited[i] = false;}}

    7. 含有相同元素求排列


    題目描述:數組元素可能含有相同的元素,進行排列時就有可能出現重復的排列,要求重復的排列只返回一個。

    在實現上,和 Permutations 不同的是要先排序,然后在添加一個元素時,判斷這個元素是否等于前一個元素,如果等于,并且前一個元素還未訪問,那么就跳過這個元素。

    public List<List<Integer>> permuteUnique(int[] nums) {List<List<Integer>> permutes = new ArrayList<>();List<Integer> permuteList = new ArrayList<>();Arrays.sort(nums);boolean[] hasVisited = new boolean[nums.length];backtracking(permuteList, permutes, hasVisited, nums);return permutes;}private void backtracking(List<Integer> permuteList, List<List<Integer>> permutes, boolean[] visited, int[] nums) {if (permuteList.size() == nums.length) {permutes.add(new ArrayList<>(permuteList));return;}for (int i = 0; i < visited.length; i++) {if (i != 0 && nums[i] == nums[i - 1] && !visited[i - 1]) {continue; //防止重復}if (visited[i]) {continue;}visited[i] = true;permuteList.add(nums[i]);backtracking(permuteList, permutes, visited, nums);permuteList.remove(permuteList.size() - 1);visited[i] = false;}}

    8. 組合

    https://leetcode-cn.com/problems/combinations

    public List<List<Integer>> combine(int n, int k) {List<List<Integer>> combinations = new ArrayList<>();List<Integer> combineList = new ArrayList<>();backtracking(combineList, combinations, 1, k, n);return combinations;}private void backtracking(List<Integer> combineList, List<List<Integer>> combinations, int start, int k, int n) {if (k == 0) {combinations.add(new ArrayList<>(combineList));return;}for (int i = start; i <= n - k + 1; i++) {combineList.add(i);backtracking(combineList, combinations, i + 1, k - 1, n);combineList.remove(combineList.size() - 1);}}

    9. 組合求和

    https://leetcode.com/problems/combination-sum/description/

    題目描述:給定一個無重復元素的數組 candidates 和一個目標數 target ,找出 candidates 中所有可以使數字和為 target 的組合。

    candidates 中的數字可以無限制重復被選取。

    說明:

    • 所有數字(包括 target)都是正整數。
    • 解集不能包含重復的組合。
    public List<List<Integer>> combiationSum(int[] candidates, int target) {List<List<Integer>> combinations = new ArrayList<>();backtracking(new ArrayList<>(), combinations, 0, target, candidates);return combinations;}private void backtracking(ArrayList<Integer> tempCombination, List<List<Integer>> combinations, int start, int target, int[] candidates) {if (target == 0) {combinations.add(new ArrayList<>(tempCombination));return;}for (int i = start; i < candidates.length; i++) {if (candidates[i] <= target) {tempCombination.add(candidates[i]);backtracking(tempCombination, combinations, i, target - candidates[i], candidates);tempCombination.remove(tempCombination.size() - 1);}}}

    10. 含有相同元素的組合求和

    https://leetcode.com/problems/combination-sum-ii/description/

    題目描述:給定一個數組 candidates 和一個目標數 target ,找出 candidates 中所有可以使數字和為 target 的組合。

    candidates 中的每個數字在每個組合中只能使用一次。

    說明:

    • 所有數字(包括目標數)都是正整數。
    • 解集不能包含重復的組合。
    public List<List<Integer>> combinationSum2(int[] candidates, int target) {List<List<Integer>> combinations = new ArrayList<>();Arrays.sort(candidates);backtracking(combinations, new ArrayList<>(), new boolean[candidates.length], 0, target, candidates);return combinations;}private void backtracking(List<List<Integer>> combinations, List<Integer> combinationList, boolean[] visited, int start, int target, int[] candidates) {if (target == 0) {combinations.add(new ArrayList<>(combinationList));return;}for (int i = start; i < candidates.length; i++) {if (i != 0 && candidates[i] == candidates[i - 1] && !visited[i - 1]) {continue;}if (candidates[i] <= target) {combinationList.add(candidates[i]);visited[i] = true;backtracking(combinations, combinationList, visited, i + 1, target - candidates[i], candidates);visited[i] = false;combinationList.remove(combinationList.size() - 1);}}}

    11. 1-9 數字的組合求和

    https://leetcode.com/problems/combination-sum-iii/description/

    題目描述:找出所有相加之和為 n 的 k 個數的組合。組合中只允許含有 1 - 9 的正整數,并且每種組合中不存在重復的數字。

    說明:

    • 所有數字都是正整數。
    • 解集不能包含重復的組合。
    public List<List<Integer>> combinationSum3(int k, int n) {List<List<Integer>> combinations = new ArrayList<>();List<Integer> combinationList = new ArrayList<>();backtracking(combinationList, combinations, 1, k, n);return combinations;}private void backtracking(List<Integer> combinationList, List<List<Integer>> combinations, int start, int k, int target) {if (k == 0 && target == 0) {combinations.add(new ArrayList<>(combinationList));return;}if (k == 0 || target == 0) {return;}for (int i = start; i <= 9; i++) {combinationList.add(i);backtracking(combinationList, combinations, i + 1, k - 1, target - i);combinationList.remove(combinationList.size() - 1);}}

    12. 子集

    https://leetcode.com/problems/subsets-ii/description/

    題目描述:找出集合的所有子集,子集不能重復,[1, 2] 和 [2, 1] 這種子集算重復

    public List<List<Integer>> subsets(int[] nums) {List<List<Integer>> subsets = new ArrayList<>();List<Integer> tempSubset = new ArrayList<>();for (int size = 0; size <= nums.length; size++) {backtracking(subsets, tempSubset, size, 0, nums);}return subsets;}private void backtracking(List<List<Integer>> subsets, List<Integer> tempSubset, int size, int start, int[] nums) {if (size == 0) {subsets.add(new ArrayList<>(tempSubset));}for (int i = start; i < nums.length; i++) {tempSubset.add(nums[i]);backtracking(subsets, tempSubset, size - 1, i + 1, nums);tempSubset.remove(tempSubset.size() - 1);}}

    13. 含有相同元素求子集


    題目描述:給定一個可能包含重復數的整數集合,返回所有可能的子集(冪集)。

    注意:解決方案集不能包含重復的子集。

    public List<List<Integer>> subsets(int[] nums) {List<List<Integer>> subsets = new ArrayList<>();List<Integer> tempSubset = new ArrayList<>();for (int size = 0; size <= nums.length; size++) {backtracking(subsets, tempSubset, size, 0, nums);}return subsets;}private void backtracking(List<List<Integer>> subsets, List<Integer> tempSubset, int size, int start, int[] nums) {if (size == 0) {subsets.add(new ArrayList<>(tempSubset));}for (int i = start; i < nums.length; i++) {tempSubset.add(nums[i]);backtracking(subsets, tempSubset, size - 1, i + 1, nums);tempSubset.remove(tempSubset.size() - 1);}}

    14. 分割字符串使得每個部分都是回文數

    https://leetcode-cn.com/problems/palindrome-partitioning

    題目描述:給定一個字符串 s,將 s 分割成一些子串,使每個子串都是回文串。

    返回 s 所有可能的分割方案。

    public List<List<String>> partition(String s) {List<List<String>> partitions = new ArrayList<>();List<String> tempPartition = new ArrayList<>();doPartition(s, partitions, tempPartition);return partitions;}private void doPartition(String s, List<List<String>> partitions, List<String> tempPartition) {if (s.length() == 0) {partitions.add(new ArrayList<>(tempPartition));return;}for (int i = 0; i < s.length(); i++) {if (isPalindrome(s, 0, i)) {tempPartition.add(s.substring(0, i + 1));doPartition(s.substring(i + 1), partitions, tempPartition);tempPartition.remove(tempPartition.size() - 1);}}}private boolean isPalindrome(String s, int begin, int end) {while (begin < end) {if (s.charAt(begin++) != s.charAt(end--)) {return false;}}return true;}

    15. 數獨

    https://leetcode-cn.com/problems/sudoku-solver/solution/jie-shu-du-by-leetcode/


    題目描述:編寫一個程序,通過已填充的空格來解決數獨問題。

    一個數獨的解法需遵循如下規則:

    • 數字 1-9 在每一行只能出現一次。
    • 數字 1-9 在每一列只能出現一次。
    • 數字 1-9 在每一個以粗實線分隔的 3x3 宮內只能出現一次。
    • 空白格用 ‘.’ 表示。
    private boolean[][] rowsUsed = new boolean[9][10];private boolean[][] colsUsed = new boolean[9][10];private boolean[][] cubesUsed = new boolean[9][10];private char[][] board;public void solveSudoku(char[][] board) {this.board = board;for (int i = 0; i < 9; i++) {for (int j = 0; j < 9; j++) {if (board[i][j] == '.') {continue;}int num = board[i][j] - '0';rowsUsed[i][num] = true;colsUsed[j][num] = true;cubesUsed[cubes(i, j)][num] = true;}backtracking(0, 0);}}private boolean backtracking(int row, int col) {while (row < 9 && board[row][col] != '.') {row = col == 8 ? row + 1 : row;col = col == 8 ? 0 : col + 1;}if (row == 9) {return true;}for (int num = 1; num <= 9; num++) {if (rowsUsed[row][num] || colsUsed[col][num] || cubesUsed[cubes(row, col)][num]) {continue;}rowsUsed[row][num] = colsUsed[col][num] = cubesUsed[cubes(row, col)][num] == true;board[row][col] = (char) (num + '0');if (backtracking(row, col)) {return true;}board[row][col] = '.';rowsUsed[row][num] = colsUsed[col][num] = cubesUsed[cubes(row, col)][num] == false;}return false;}private int cubes(int i, int j) {int r = i / 3;int c = j / 3;return r * 3 + c;}

    16. N皇后

    https://leetcode-cn.com/problems/n-queens/solution/nhuang-hou-by-leetcode/
    題目描述:n 皇后問題研究的是如何將 n 個皇后放置在 n×n 的棋盤上,并且使皇后彼此之間不能相互攻擊。

    上圖為 8 皇后問題的一種解法。

    給定一個整數 n,返回所有不同的 n 皇后問題的解決方案。

    每一種解法包含一個明確的 n 皇后問題的棋子放置方案,該方案中 ‘Q’ 和 ‘.’ 分別代表了皇后和空位。

    private List<List<String>> solutions;private char[][] nQueues;private boolean[] colUsed;private boolean[] diagonals45Used;private boolean[] diagonals135Used;private int n;public List<List<String>> solveNQueues(int n) {solutions = new ArrayList<>();nQueues = new char[n][n];for (int i = 0; i < n; i++) {Arrays.fill(nQueues[i], '.');}colUsed = new boolean[n];diagonals45Used = new boolean[2 * n - 1];diagonals135Used = new boolean[2 * n - 1];this.n = n;backtracking(0);return solutions;}private void backtracking(int row) {if (row == n) {List<String> list = new ArrayList<>();for (char[] chars : nQueues) {list.add(new String(chars));}solutions.add(list);return;}for (int col = 0; col < n; col++) {int diagonals45Idx = row + col;int diagonals135Idx = n - 1 - (row - col);if (colUsed[col] || diagonals45Used[diagonals45Idx] || diagonals135Used[diagonals135Idx]) {continue;}nQueues[row][col] = 'Q';colUsed[col] = diagonals45Used[diagonals45Idx] = diagonals135Used[diagonals135Idx] = true;backtracking(row + 1);colUsed[col] = diagonals45Used[diagonals45Idx] = diagonals135Used[diagonals135Idx] = false;nQueues[row][col] = '.';}}

    總結

    以上是生活随笔為你收集整理的LeetCode——Backtracking的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。