• 回溯系列--11个题


    组合问题

    第77题. 组合

    题⽬链接:https://leetcode-cn.com/problems/combinations/

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

    ⽰例: 输⼊: n = 4, k = 2 输出: [ [2,4], [3,4], [2,3], [1,2], [1,3], [1,4], ]

    1. class Solution {
    2. List> result = new ArrayList<>();
    3. // List path = new ArrayList<>(); LinkedList增添的时间复杂度更低
    4. LinkedList path = new LinkedList<>();
    5. public List> combine(int n, int k) {
    6. // backtraking(n, k, 0); 返回范围 [1, n] 中所有可能的 k 个数的组合。所以index从1开始
    7. backtraking(n, k, 1);
    8. return result;
    9. }
    10. void backtraking(int n, int k, int index) {
    11. if(path.size() == k) {
    12. // result.add(path); new ArrayList<>() 将LinkedList类型的path转换为ArrayList类型
    13. result.add(new ArrayList<>(path));
    14. return;
    15. }
    16. for(int i = index; i <= n; i++){
    17. path.add(i);
    18. // backtraking(n, k , index + 1);
    19. backtraking(n, k ,i + 1);
    20. path.remove(path.size() - 1);
    21. // path.removeLast();
    22. }
    23. }
    24. }

    第216题.组合总和III

    链接:https://leetcode-cn.com/problems/combination-sum-iii/

    找出所有相加之和为 n 的 k 个数的组合。组合中只允许含有 1 - 9 的正整数,并且每种组合 中不存在重复的数字。 说明: 所有数字都是正整数。 解集不能包含重复的组合。

    ⽰例 1: 输⼊: k = 3, n = 7 输出: [[1,2,4]]

    ⽰例 2: 输⼊: k = 3, n = 9 输出: [[1,2,6], [1,3,5], [2,3,4]]

    1. class Solution {
    2. List> result = new ArrayList<>();
    3. LinkedList path = new LinkedList<>();
    4. public List> combinationSum3(int k, int n) {
    5. backtracking(k, n, 0, 1);
    6. return result;
    7. }
    8. void backtracking(int k, int n,int sum, int index) {
    9. if(sum == n && path.size() == k) {
    10. result.add(new ArrayList<>(path));
    11. return;
    12. }
    13. for(int i = index; i <= 9 && n >= sum + i; i++) {
    14. path.add(i);
    15. sum += i;
    16. backtracking(k, n, sum, i + 1);
    17. sum -= i;
    18. path.remove(path.size() - 1);
    19. }
    20. }
    21. }

    17.电话号码的字母组合

    题⽬链接:https://leetcode-cn.com/problems/letter-combinations-of-a-phone-number/

    给定⼀个仅包含数字 2-9 的字符串,返回所有它能表⽰的字母组合。 给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。

    ⽰例: 输⼊:"23" 输出:["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"].

    说明:尽管上⾯的答案是按字典序排列的,但是你可以任意选择答案输出的顺序。

    1. class Solution {
    2. String[] letterMap = new String[]{
    3. "",//0
    4. "",//1
    5. "abc",//2
    6. "def",//3
    7. "ghi",//4
    8. "jkl",//5
    9. "mno",//6
    10. "pqrs",//7
    11. "tuv",//8
    12. "wxyz"//9
    13. };
    14. List result = new ArrayList<>();
    15. StringBuilder path = new StringBuilder();
    16. public List letterCombinations(String digits) {
    17. if(digits == null || digits.length() == 0) return result;
    18. backTracking(digits, 0);
    19. return result;
    20. }
    21. void backTracking(String digits, int index) {
    22. if(index == digits.length()) {
    23. result.add(path.toString());
    24. return;
    25. }
    26. String s = letterMap[digits.charAt(index) - '0'];
    27. for(int i = 0; i < s.length(); i++){ //对每个按键的水平遍历
    28. path.append(s.charAt(i));
    29. backTracking(digits, index + 1); //对不同按键的深度递归
    30. path.deleteCharAt(path.length() - 1);
    31. }
    32. }
    33. }

    39. 组合总和

    题⽬链接:https://leetcode-cn.com/problems/combination-sum/

    给定⼀个⽆重复元素的数组 candidates 和⼀个⽬标数 target ,找出 candidates 中所有可以 使数字和为 target 的组合。 candidates 中的数字可以⽆限制重复被选取。

    说明: 所有数字(包括 target)都是正整数。 解集不能包含重复的组合。

    ⽰例 1: 输⼊:candidates = [2,3,6,7], target = 7, 所求解集为: [ [7], [2,2,3] ]

    ⽰例 2: 输⼊:candidates = [2,3,5], target = 8, 所求解集为: [ [2,2,2,2], [2,3,3], [3,5] ]

    1. class Solution {
    2. List> result = new ArrayList<>();
    3. LinkedList path = new LinkedList<>();
    4. public List> combinationSum(int[] candidates, int target) {
    5. Arrays.sort(candidates);
    6. backtracking(candidates, target, 0, 0);
    7. return result;
    8. }
    9. void backtracking(int[] candidates, int target, int sum, int index) {
    10. if(target == sum) {
    11. // result.add(path);
    12. result.add(new ArrayList<>(path));
    13. return;
    14. }
    15. for(int i = index; i < candidates.length && target >= sum + i; i++){ //target >= sum + i要提前排序
    16. path.add(candidates[i]);
    17. sum += candidates[i];
    18. backtracking(candidates, target, sum, i);
    19. sum -= candidates[i];
    20. path.remove(path.size() - 1);
    21. }
    22. }
    23. }

    40.组合总和II

    题⽬链接:https://leetcode-cn.com/problems/combination-sum-ii/

    给定⼀个数组 candidates 和⼀个⽬标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。 candidates 中的每个数字在每个组合中只能使⽤⼀次。

    说明: 所有数字(包括⽬标数)都是正整数。 解集不能包含重复的组合。

    ⽰例 1: 输⼊: candidates = [10,1,2,7,6,1,5], target = 8, 所求解集为: [ [1, 7], [1, 2, 5], [2, 6], [1, 1, 6] ]

    ⽰例 2: 输⼊: candidates = [2,5,2,1,2], target = 5, 所求解集为: [ [1,2,2], [5] ]

    1. class Solution {
    2. // public List> combinationSum2(int[] candidates, int target) {
    3. List> result = new ArrayList<>();
    4. LinkedList path = new LinkedList<>();
    5. boolean[] used;
    6. public List> combinationSum2(int[] candidates, int target) {
    7. used = new boolean[candidates.length];
    8. Arrays.fill(used, false);
    9. Arrays.sort(candidates);
    10. backtracking(candidates, target, 0, 0);
    11. return result;
    12. }
    13. void backtracking(int[] candidates, int target, int sum, int index) {
    14. if(target == sum) {
    15. // result.add(path);
    16. result.add(new ArrayList<>(path));
    17. return;
    18. }
    19. // for(int i = index; i < candidates.length && target >= sum + i; i++){ //target >= sum + i要提前排序
    20. for(int i = index; i < candidates.length && target >= sum + candidates[i]; i++){
    21. // if(i > 0 && candidates[i-1] == candidates[i] && used[i - 1] == false){
    22. if(i > 0 && candidates[i-1] == candidates[i] && used[i - 1] == false){
    23. continue;
    24. }
    25. path.add(candidates[i]);
    26. sum += candidates[i];
    27. used[i] = true;
    28. backtracking(candidates, target, sum, i + 1);
    29. used[i] = false;
    30. sum -= candidates[i];
    31. path.remove(path.size() - 1);
    32. }
    33. }
    34. }

    分割问题

    131.分割回⽂串

    题⽬链接:https://leetcode-cn.com/problems/palindrome-partitioning/

    给定⼀个字符串 s,将 s 分割成⼀些⼦串,使每个⼦串都是回⽂串。 返回 s 所有可能的分割⽅案。

    ⽰例: 输⼊: "aab" 输出: [ ["aa","b"], ["a","a","b"] ]

    1. class Solution {
    2. List> result = new ArrayList<>();
    3. LinkedList path = new LinkedList<>();
    4. public List> partition(String s) {
    5. backtracking(s, 0);
    6. return result;
    7. }
    8. void backtracking(String s, int index) {
    9. if(index == s.length()) {
    10. // result.add(path);
    11. result.add(new ArrayList(path));
    12. return;
    13. }
    14. for(int i = index; i < s.length(); i++) {
    15. if(isvalid(s, index ,i)) {
    16. // path.add(s.subStr(i, index));
    17. // path.add(s.substring(i+1, index));
    18. path.add(s.substring(index, i+1));
    19. backtracking(s, i+1);
    20. path.removeLast();
    21. }else {
    22. continue;
    23. }
    24. }
    25. }
    26. boolean isvalid(String s, int startIndex, int end) {
    27. for (int i = startIndex, j = end; i < j; i++, j--) {
    28. if (s.charAt(i) != s.charAt(j)) {
    29. return false;
    30. }
    31. }
    32. return true;
    33. }
    34. }

    子集问题

    第78题. ⼦集

    题⽬地址:https://leetcode-cn.com/problems/subsets/

    给定⼀组不含重复元素的整数数组 nums,返回该数组所有可能的⼦集(幂集)。

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

    ⽰例: 输⼊: nums = [1,2,3] 输出: [ [3], [1], [2], [1,2,3], [1,3], [2,3], [1,2], [] ]

    1. class Solution {
    2. List> result = new ArrayList<>();
    3. LinkedList path = new LinkedList<>();
    4. public List> subsets(int[] nums) {
    5. backStraking(nums, 0);
    6. return result;
    7. }
    8. void backStraking(int[] nums, int index) {
    9. result.add(new ArrayList<>(path));
    10. if(index >= nums.length) {
    11. return;
    12. }
    13. for(int i = index; i < nums.length; i++) {
    14. path.add(nums[i]);
    15. // backStraking(nums, index +1); 怎么能用index呢?!
    16. backStraking(nums, i +1);
    17. path.removeLast();
    18. }
    19. }
    20. }

    491.递增⼦序列

    题⽬链接:https://leetcode-cn.com/problems/increasing-subsequences/

    给定⼀个整型数组, 你的任务是找到所有该数组的递增⼦序列,递增⼦序列的长度⾄少是 2。

    ⽰例: 输⼊: [4, 6, 7, 7] 输出: [[4, 6], [4, 7], [4, 6, 7], [4, 6, 7, 7], [6, 7], [6, 7, 7], [7,7], [4,7,7]]

    说明: 给定数组的长度不会超过15。

    ·        数组中的整数范围是 [-100,100]。

            给定数组中可能包含重复数字,相等的数字应该被视为递增的⼀种情况。

    1. class Solution {
    2. List> result = new ArrayList<>();
    3. LinkedList path = new LinkedList<>();
    4. public List> findSubsequences(int[] nums) {
    5. backtracking(nums,0);
    6. return result;
    7. }
    8. void backtracking(int[] nums,int index) {
    9. if(path.size() > 1) { //递增子序列长度至少为2
    10. result.add(new ArrayList<>(path));
    11. }
    12. if(index == nums.length){
    13. return;
    14. }
    15. boolean[] used = new boolean[201]; //同一层相同结点不能重复
    16. for(int i = index; i < nums.length; i++) {
    17. //纵向判断递增
    18. if(path.size() > 0 && nums[i] < path.get(path.size() - 1)) {
    19. continue;
    20. }
    21. //横向判断元素是否重复(序列无序)
    22. if(used[nums[i] + 100] == true) {
    23. continue;
    24. }
    25. // used[nums[i]] = true; 因为下标没有负数
    26. used[nums[i] + 100] = true;
    27. path.add(nums[i]);
    28. backtracking(nums, i + 1);
    29. path.removeLast();
    30. }
    31. }
    32. }

    排列问题

    46.全排列

    题⽬链接:https://leetcode-cn.com/problems/permutations/

    给定⼀个 没有重复 数字的序列,返回其所有可能的全排列。

    ⽰例: 输⼊: [1,2,3] 输出: [ [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1] ]

    1. class Solution {
    2. List> result = new ArrayList<>();
    3. LinkedList path = new LinkedList<>();
    4. public List> permute(int[] nums) {
    5. boolean[] used = new boolean[nums.length + 1];
    6. Arrays.fill(used, false);
    7. backtracking(nums,used);
    8. return result;
    9. }
    10. //同一树枝标记用过 used[i] == true
    11. //将used作为参数传递 比较的是同一树枝和同一树层
    12. //将used放在for循环上面,比较的是for循环是否有重复元素
    13. void backtracking(int[] nums, boolean[] used) {
    14. if(path.size() == nums.length) {
    15. result.add(new ArrayList<>(path));
    16. return;
    17. }
    18. for(int i = 0; i < nums.length; i++) {
    19. if(used[i] == true) {
    20. continue;
    21. }
    22. used[i] = true;
    23. path.add(nums[i]);
    24. backtracking(nums, used);
    25. path.remove(path.size() - 1);
    26. used[i] = false;
    27. }
    28. }
    29. }

    47.全排列 II

    题⽬链接:https://leetcode-cn.com/problems/permutations-ii/

    给定⼀个可包含重复数字的序列 nums ,按任意顺序 返回所有不重复的全排列。

    ⽰例 1: 输⼊:nums = [1,1,2] 输出: [[1,1,2], [1,2,1], [2,1,1]]

    ⽰例 2: 输⼊:nums = [1,2,3] 输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]

    提⽰: 1 <= nums.length <= 8 -10 <= nums[i] <= 10

    1. class Solution {
    2. List> result = new ArrayList<>();
    3. LinkedList path = new LinkedList<>();
    4. int len;
    5. public List> permuteUnique(int[] nums) {
    6. len = nums.length;
    7. boolean[] used = new boolean[nums.length + 1]; //[]是长度 <>是范型 ()是内容
    8. Arrays.fill(used, false);
    9. Arrays.sort(nums);
    10. backTracking(nums,used);
    11. return result;
    12. }
    13. void backTracking(int[] nums, boolean[] used){
    14. if(path.size() == nums.length) {
    15. result.add(new ArrayList<>(path));
    16. return;
    17. }
    18. for(int i = 0; i < len; i++) {
    19. //纵向判断
    20. if(used[i] == true) continue;
    21. //横向判断 原序列需要排序
    22. if(i > 0 && nums[i] == nums[i-1] && used[i-1] == false) continue;
    23. used[i] = true;
    24. path.add(nums[i]);
    25. backTracking(nums, used);
    26. path.removeLast();
    27. used[i] = false;
    28. }
    29. }
    30. }

    棋盘问题

    第51题. N皇后

    题⽬链接: https://leetcode-cn.com/problems/n-queens/ n

    皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。

    8 皇后问题的⼀种解法:

    给定⼀个整数 n,返回所有不同的 n 皇后问题的解决⽅案。 每⼀种解法包含⼀个明确的 n 皇后问题的棋⼦放置⽅案,该⽅案中 'Q' 和 '.' 分别代表了皇后 和空位。

    ⽰例: 输⼊: 4 输出: [ [".Q..",  "...Q", "Q...", "..Q."],["..Q.",  "Q...", "...Q", ".Q.."] ] 解释: 4 皇后问题存在两个不同的解法。

    1. class Solution {
    2. List> result = new ArrayList<>();
    3. public List> solveNQueens(int n) {
    4. char[][] chessboard = new char[n][n];
    5. for(char[] c : chessboard) {
    6. Arrays.fill(c,'.');
    7. }
    8. backtracking(n, 0, chessboard);
    9. return result;
    10. }
    11. void backtracking(int n, int row, char[][] chessboard){
    12. if(row == n) {
    13. result.add(Array2List(chessboard));
    14. return;
    15. }
    16. for(int col = 0; col < n; col++) { //行和列都是从0开始
    17. if(isvalid(n,row,col,chessboard)) {
    18. chessboard[row][col] = 'Q';
    19. backtracking(n, row + 1, chessboard);
    20. chessboard[row][col] = '.';
    21. }
    22. }
    23. }
    24. public List Array2List(char[][] chessboard) {
    25. List list = new ArrayList<>();
    26. for (char[] c : chessboard) {
    27. list.add(String.copyValueOf(c));
    28. }
    29. return list;
    30. }
    31. public boolean isvalid(int n, int row, int col, char[][] chessboard) {
    32. // 检查列
    33. for (int i=0; i
    34. if (chessboard[i][col] == 'Q') {
    35. return false;
    36. }
    37. }
    38. // 检查45度对角线
    39. for (int i=row-1, j=col-1; i>=0 && j>=0; i--, j--) {
    40. if (chessboard[i][j] == 'Q') {
    41. return false;
    42. }
    43. }
    44. // 检查135度对角线
    45. for (int i=row-1, j=col+1; i>=0 && j<=n-1; i--, j++) {
    46. if (chessboard[i][j] == 'Q') {
    47. return false;
    48. }
    49. }
    50. return true;
    51. }
    52. }

  • 相关阅读:
    Mainflux IoT:Go语言轻量级开源物联网平台,支持HTTP、MQTT、WebSocket、CoAP协议
    SpringBoot对于SpringMVC的支持
    验证UDP端口是否开放
    数据结构 【树状数组】【线段树】【珂朵莉树】
    【ML-SVM案例学习】案例一:对鸢尾花数据进行SVM分类(附源码)
    ElasticSearch7.3学习(二)----内部基于_version乐观锁控制机制
    【汇编语言-王爽】第八章:数据处理的两个基本问题
    【Linux】常用命令汇总
    请看看我的stata回归分析思路有没有问题?
    一文讲清Java中的四种引用类型的区别(关于弱引用是如何解决ThreadLocal内存泄漏问题)
  • 原文地址:https://blog.csdn.net/m0_48489427/article/details/132848698