• 每日一题~组合总数III


    原题链接:216. 组合总和 III - 力扣(LeetCode)

    题目描述:

    思路分析:

    这是一个组合的问题,所以我们可以使用深度优先搜索(DFS)的方式将所有的情况都列举出来,然后将其中符合条件的情况添加到列表中,最后返回这个列表就可以了。详细步骤如下:

    1、准备一个 tmp 列表保存当前集合的数据,用 list 列表保存所有符合条件的列表,用 sum 来记录当前 tmp 列表中的数据之和,用一个 used 数组来记录该数据是否已经被使用

    2、使用 DFS 来找到所有组合,当 tmp 的 size = k 时,说明 tmp 已经满了,如果 sum = n,说明这个 tmp 符合条件,但是需要注意的是【1,2,3】和【1,3,2】是属于同一个集合,所以我们还需要进行去重操作,因为我们是从小到大来搜索的,所以【1,2,3】一定在【1,3,2】的前面,去重的时候我们只需要判断 tmp.get(i+1) 是否小于 tmp.get(i) 就可以了,如果 tmp.get(i+1) < tmp.get(i),则说明 list 中已经保存了该情况,直接返回即可

    代码示例:

    1. class Solution {
    2. // 标记是否使用
    3. int[] used = new int[10];
    4. // 记录链表中的数据和
    5. int sum = 0;
    6. List> list = new ArrayList<>();
    7. LinkedList tmp = new LinkedList<>();
    8. public List> combinationSum3(int k, int n) {
    9. // 递归
    10. dfs(1,k,n);
    11. return list;
    12. }
    13. public void dfs(int x,int k, int n) {
    14. if(tmp.size() == k) {
    15. if(sum == n) {
    16. // 去重操作
    17. for(int i = 0; i < k-1; i++) {
    18. if(i+1 < k && tmp.get(i) > tmp.get(i+1)) {
    19. return;
    20. }
    21. }
    22. list.add(new ArrayList<>(tmp));
    23. }
    24. return;
    25. }
    26. for(int i = x; i < 10; i++) {
    27. if(used[i] == 0) {
    28. tmp.add(i);
    29. sum += i;
    30. used[i] = 1;
    31. dfs(x+1,k,n);
    32. tmp.removeLast();
    33. sum -= i;
    34. used[i] = 0;
    35. }
    36. }
    37. }
    38. }

    可以看出,上述步骤还是比较麻烦的,我们不仅需要找出来 1~9 所有的组合情况,还需要对这些情况进行一下去重操作,这样一来效率就非常低了。如果我们在寻找组合的时候,就进行剪枝,只保存升序的列表例如,【1,2,3】,【1,2,4】,【1,2,5】,……【7,8,9】,这样的话我们就不需要找到所有的组合情况,而且还节省了去重的步骤,相比第一种暴力的解决方法就显得高效了很多。

    1. class Solution {
    2. // 标记是否使用
    3. int[] used = new int[10];
    4. // 记录链表中的数据和
    5. int sum = 0;
    6. List> list = new ArrayList<>();
    7. LinkedList tmp = new LinkedList<>();
    8. public List> combinationSum3(int k, int n) {
    9. // 递归
    10. dfs(1,k,n);
    11. return list;
    12. }
    13. public void dfs(int x,int k, int n) {
    14. if(tmp.size() == k) {
    15. if(sum == n) list.add(new ArrayList<>(tmp));
    16. return;
    17. }
    18. for(int i = x; i < 10; i++) {
    19. if(used[i] == 0) {
    20. // 剪枝
    21. if(tmp.size() > 0 && i < tmp.peekLast()) continue;
    22. tmp.add(i);
    23. sum += i;
    24. used[i] = 1;
    25. dfs(x+1,k,n);
    26. tmp.removeLast();
    27. sum -= i;
    28. used[i] = 0;
    29. }
    30. }
    31. }
    32. }

  • 相关阅读:
    SoftwareTest3 - 要了人命的Bug
    【Gradle】四、使用Gradle创建SringBoot微服务项目
    linux环境安装cmake
    linux C.UTF-8和en-US.UTF-8语言环境有什么区别?(中文乱码问题)locale命令 centos、ubuntu修改编码集(没搞定!)
    vscode远程调试c++
    linux 自带压力测试工具ab
    【[SCOI2005] 互不侵犯】【状压DP(含概念讲解)】
    我的JQuery随笔
    VISUAL SVN 5.6.0以上破解使用天数
    一篇五分生信临床模型预测文章代码复现——Figure 2. 生存分析,箱线图表达改变分析(二)
  • 原文地址:https://blog.csdn.net/qq_61139806/article/details/133265982