算法练习 Day24 | leetcode 77. 组合

一、回溯知识

1.题目分类

2.回溯模板

void backtracking(参数) {
    if (终止条件) {
        存放结果;
        return;
    }

    for (选择:本层集合中元素(树中节点孩子的数量就是集合的大小)) {
        处理节点;
        backtracking(路径,选择列表); // 递归
        回溯,撤销处理结果
    }
}

二、算法题

77. 组合

题目链接

1.未剪枝优化
class Solution {
    List<List<Integer>> result=new ArrayList<>();
    List<Integer> path=new LinkedList<>();
    public List<List<Integer>> combine(int n, int k) {
        backtracking(n, k, 1);
        return result;

    }

    public void backtracking(int n,int k,int startindex){
        //回溯函数终止条件
        if(path.size()==k){
            //当path的大小与组合大小相同时,说明找到了题目要求的组合,是回溯终止的情况
            result.add(new ArrayList<>(path));
            return;
        }
        for(int i=startindex;i<=n;i++){
            path.add(i);
            backtracking(n, k, i+1);
            path.removeLast();
        }

    }
}

  • startIndex 为了防止出现重复的组合

  • result.add(new ArrayList<>(path))这种写法是为了防止在后续的过程中对 `path` 对象的修改影响到已经加入 `result` 中的组合。
    • 如果直接使用 `result.add(path)`,那么在后续的回溯过程中,当从 `path` 中移除元素时,已经加入 `result` 的组合也会受到影响,因为它们引用的是相同的 `path` 对象
    • 通过使用 `new ArrayList<>(path)`,实际上是创建了 `path` 的一个副本,使得 `result` 中的组合与后续的回溯过程互相独立,避免了相互影响。
    • 这样做是为了确保 `result` 中的组合是独立的,而不会因为后续回溯的修改而导致错误的结果。

2.剪枝优化
class Solution {
    List<List<Integer>> result=new ArrayList<>();
    List<Integer> path=new LinkedList<>();
    public List<List<Integer>> combine(int n, int k) {
        backtracking(n, k, 1);
        return result;

    }

    public void backtracking(int n,int k,int startindex){
        //回溯函数终止条件
        if(path.size()==k){
            //当path的大小与组合大小相同时,说明找到了题目要求的组合,是回溯终止的情况
            result.add(new ArrayList<>(path));
            return;
        }
        for(int i=startindex;i<=n-(k-path.size())+1;i++){
            path.add(i);
            backtracking(n, k, i+1);
            path.removeLast();
        }

    }
}
  •  只修改了循环中的i的判断条件

    • 已经选择的元素个数:path.size();

    • 还需要的元素个数为: k - path.size();

    • 下一个选取的元素在集合n的起始位置 : n - (k - path.size()) + 1,开始遍历

      • 比如

      • 取了1后,n - (k - path.size()) + 1=2,下一个元素要从2开始选,直接选定开始元素为1,不再尝试取2,3,4为开头,然后进入下一层循环

    • 为什么有个+1呢,因为包括起始位置,我们要是一个左闭的集合。

      举个例子,n

相关推荐

  1. 代码随想录算法训练营Day24|77. 组合

    2024-01-22 13:38:01       38 阅读
  2. 代码随想录算法训练营day26 | 77. 组合

    2024-01-22 13:38:01       10 阅读
  3. 算法练习Day24Leetcode/Python-回溯算法

    2024-01-22 13:38:01       40 阅读
  4. LeetCode练习与总结:组合-77

    2024-01-22 13:38:01       11 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-01-22 13:38:01       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-01-22 13:38:01       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-01-22 13:38:01       19 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-01-22 13:38:01       20 阅读

热门阅读

  1. 计算机通信:HTTP协议

    2024-01-22 13:38:01       34 阅读
  2. 编程笔记 html5&css&js 050 CSS表格2-1

    2024-01-22 13:38:01       28 阅读
  3. Golang爬虫技术

    2024-01-22 13:38:01       36 阅读
  4. 用go语言删除重复文件

    2024-01-22 13:38:01       36 阅读
  5. Vue.js:构建用户界面的渐进式框架

    2024-01-22 13:38:01       27 阅读
  6. 华为网络设备常用命令大全

    2024-01-22 13:38:01       44 阅读
  7. Vue 批量注册全局组件

    2024-01-22 13:38:01       34 阅读
  8. props传值

    2024-01-22 13:38:01       37 阅读
  9. Spring与Spring Boot:区别与Spring Boot的实战示例

    2024-01-22 13:38:01       29 阅读