• LeetCode 热题 100(九):回溯复习。77. 组合、17. 电话号码的字母组合、39. 组合总和


    题目一:

    77. 组合

    思路:

    思路:回溯算法。使用回溯三部曲进行解题:

    1.递归函数的返回值以及参数:n,k,startIndex(记录每次循环集合从哪里开始遍历的位置),其中startIndex 就是防止出现重复的组合。比如从1开始了循环,则使用startindex=2,让startindex作为下次循环的开始。

    还有全局变量:一个是用来存放一个符合条件的结果path,一个用来存放所有符合条件的结果集合result。

    2.回溯函数终止条件:path这个数组的大小如果达到k,说明我们找到了一个子集大小为k的组合,在图中path存的就是根节点到叶子节点的路径

    3.单层搜索的过程:for循环用来横向遍历,递归的过程是纵向遍历。
    代码:

    1. class Solution {
    2. // 存放单个结果path, 存放所有结果res
    3. List<List<Integer>> res = new ArrayList<>();
    4. LinkedList<Integer> path = new LinkedList<>();
    5. public List<List<Integer>> combine(int n, int k) {
    6. combineHelper(n, k, 1);
    7. return res;
    8. }
    9. // startindex就是循环开始位置
    10. private void combineHelper(int n, int k, int startindex) {
    11. // 终止条件
    12. if (path.size() == k){
    13. res.add(new ArrayList<>(path));
    14. return;
    15. }
    16. // 单层逻辑
    17. for (int i = startindex; i <= n ; i++ ){
    18. path.add(i);
    19. combineHelper(n, k, i + 1);
    20. path.removeLast();
    21. }
    22. }
    23. }

    题目二:

    17. 电话号码的字母组合

    思路:同组合。不过换成了对字符串的使用,细节见代码。

    代码:

    1. class Solution {
    2. // 存储结果的集合
    3. List res = new ArrayList<>();
    4. // 存储结果,类似组合问题中的path
    5. StringBuilder temp = new StringBuilder();
    6. public List letterCombinations(String digits){
    7. // 初始判断
    8. if (digits.length() == 0 || digits == null) return res;
    9. // 先设置好电话号码对应的字母
    10. String[] numString = {"","","abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};
    11. zimuzuhe(digits, numString, 0);
    12. return res;
    13. }
    14. // s代表输入的数字,
    15. private void zimuzuhe(String s, String[] numString, int num) {
    16. // temp.length 也可以换成 num,我习惯比较path.size与k的使用, temp.length等同于path.size,k等同于s.length
    17. if (temp.length() == s.length()){
    18. res.add(temp.toString());
    19. return;
    20. }
    21. // num指代的是字符串中数字的位置索引,比如“23”,num会分别等于0,1。因为是使用charAt去获取的str
    22. String str = numString[s.charAt(num) - '0'];
    23. for (int i = 0; i < str.length(); i++){
    24. temp.append(str.charAt(i));
    25. zimuzuhe(s, numString, num + 1);
    26. temp.deleteCharAt(temp.length() - 1);
    27. }
    28. }
    29. }
    题目三;

    39. 组合总和

    思路:回溯。但因为本题区别普通组合问题可以重复使用数字,需要对startIndex进行调整

    代码:

    1. class Solution {
    2. List> res = new ArrayList<>();
    3. LinkedList path = new LinkedList<>();
    4. public List> combinationSum(int[] candidates, int target){
    5. if (candidates.length == 0) return res;
    6. // 排序,以防重复,因为每个数字可以多次取
    7. Arrays.sort(candidates);
    8. // 用于判断总和
    9. int sum = 0;
    10. // 每次循环的起始位置
    11. int startIndex = 0;
    12. sum_zuhe(candidates, target, sum, startIndex);
    13. return res;
    14. }
    15. private void sum_zuhe(int[] candidates, int target, int sum, int startIndex) {
    16. // 总和判断
    17. if (sum == target){
    18. res.add(new ArrayList<>(path));
    19. return;
    20. }
    21. // 虽然可以重复使用数字,但仍然是组合问题,只是每次的起始点不再+1
    22. for (int i = startIndex; i < candidates.length; i++){
    23. if (sum + candidates[i] > target) break;
    24. path.add(candidates[i]);
    25. sum += candidates[i];
    26. // 使用i为起始点,不再i+1,因为可重复使用
    27. sum_zuhe(candidates, target, sum, i);
    28. sum -= candidates[i];
    29. path.removeLast();
    30. }
    31. }
    32. }

  • 相关阅读:
    面向对象设计原则总结:SOLID/LKP/DRY/KISS…
    SwiftUI之iOS16中的三种SF字体的样式和使用
    Java 实现RSA 加解密算法 公钥加密传参
    【Python 千题 —— 基础篇】输出可以被5整除的数
    Smartbi电子表格故事之高效营销活动后的自助数据分析
    Kafka SASL认证授权(六)全方位性能测试
    JavaEE——No.1 线程安全问题
    ECR - Elastic Container Registry
    如何系统性的学习报关知识
    面试题: Hive-SQL查询连续活跃登录用户思路详解
  • 原文地址:https://blog.csdn.net/xiaomingming99/article/details/132939848