第七章回溯_组合

吾日三省吾身

还记得的梦想吗

正在努力实现它吗

可以坚持下去吗


力扣题号:77. 组合 - 力扣(LeetCode)

下述题目描述和示例均来自力扣

题目描述

给定两个整数 nk,返回范围 [1, n] 中所有可能的 k 个数的组合。

你可以按 任何顺序 返回答案。

示例

示例 1:

复制代码
输入:n = 4, k = 2
输出:
[
  [2,4],
  [3,4],
  [2,3],
  [1,2],
  [1,3],
  [1,4],
]

示例 2:

复制代码
输入:n = 1, k = 1
输出:[[1]]

提示:

  • 1 <= n <= 20
  • 1 <= k <= n

思路

Java解法一:回溯算法

我们利用递归,在递归之中回溯,挨个的寻找我们所需要的目标。找到一个之后就删除最后那一个,这就是一个回溯的操作,然后再找。具体代码如下:

java 复制代码
class Solution {
    // 先创建两个全局变量
    List<List<Integer>> res = new ArrayList<>();
    LinkedList<Integer> path = new LinkedList<>();

    public List<List<Integer>> combine(int n, int k) {
        // 进入递归搜索
        backtracking(n, k, 1);
        // 此时已经递归回溯完毕,结果已经保存到了res中直接返回即可
        return res;
    }

    public void backtracking(int n, int k, int startIndex) {
        // 递归结束条件就是当前的元素集已经达到了k个
        if (path.size() == k){
            // 由于我们的path是linkedlist类型,所以要保存到res中要先转换乘Arraylist
            res.add(new ArrayList<>(path));
            // 终止
            return;
        }
        // 进入寻找过程
        for (int i = startIndex; i <= n ; i++) {
            path.add(i);
            backtracking(n, k, i + 1);
            // 删除最后一个元素,回溯
            path.removeLast();
        }
    }
}

拿下~!!!!


Java解法一:回溯算法剪枝操作

在回溯算法的开篇就提到了,回溯是一个暴力的枚举过程,唯一的优化方式也就是进行剪枝操作,非常幸运的是这道题就可以进行一个剪枝的操作。

思考一些问题。如果起始位置之后的元素个数已经小于我们需要的元素的个数,我们还需要在这个分支上浪费时间吗?答案显然是不需要了。

大概的优化思路如下(参考于《代码随想录》):

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

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

(3)最多从起始位置 (n - ( k - path.size() )+ 1 ) 开始遍历

因此我们也只需要改变一下for循环的结束条件这么一处代码即可

java 复制代码
class Solution {
    // 先创建两个全局变量
    List<List<Integer>> res = new ArrayList<>();
    LinkedList<Integer> path = new LinkedList<>();

    public List<List<Integer>> combine(int n, int k) {
        // 进入递归搜索
        backtracking(n, k, 1);
        // 此时已经递归回溯完毕,结果已经保存到了res中直接返回即可
        return res;
    }

    public void backtracking(int n, int k, int startIndex) {
        // 递归结束条件就是当前的元素集已经达到了k个
        if (path.size() == k){
            // 由于我们的path是linkedlist类型,所以要保存到res中要先转换乘Arraylist
            res.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();
        }
    }
}

总结

组合问题是回溯算法的典型题目。可以通过剪枝的方法来优化我们的回溯代码~~

ヾ( ̄▽ ̄)Bye~Bye~

相关推荐
大模型码小白9 分钟前
企业级检索增强后端集成:Java 服务如何管理知识库版本
java·服务器·开发语言·人工智能·python·microsoft
我不是懒洋洋21 分钟前
从零实现一个分布式日志平台:ELK的核心设计
c++
geovindu25 分钟前
go:Backtracking Algorithm
开发语言·后端·算法·golang·回溯算法
AI多Agent协作实战派30 分钟前
AI多Agent协作系统实战(二十二):从6列到12列——任务监控报告的进化之路
java·人工智能·uni-app·bug
神仙别闹39 分钟前
基于QT(C++)实现Windows 自启动项查看和分析
c++·windows·qt
千桐科技44 分钟前
DataX 执行引擎正式加入:qData 开源版 v1.6.0 新增 Quartz + DataX 轻量运行模式!
java·大数据·开源·数据治理·数据中台·qdata
微露清风1 小时前
模拟算法学习记录
学习·算法
Irene19911 小时前
Oracle PL/SQL Developer 版本差异(11g、14)实战总结
java·开发语言
AI人工智能+电脑小能手1 小时前
【大白话说Java面试题 第191题】【08_Kafka篇】第7题:消息队列的优缺点
java·消息队列·系统设计·分布式架构·技术选型
用户446139430271 小时前
Spring Boot 接入大模型:从配置到实战的完整指南
java