【回溯算法】【组合问题】Leetcode 77.组合 216. 组合总和 III

news2024/11/15 12:11:06

【回溯算法】【回溯算法剪枝】 Leetcode 77.组合 216. 组合总和 III

  • 回溯算法可以解决的问题
  • Leetcode 77.组合
    • 解法1 回溯法三部曲,函数参数、终止条件和单层搜索逻辑
    • 解法一plus 回溯法+剪枝
  • 另一道组合回溯问题 216. 组合总和 III
    • 解法:回溯
    • 解法: 回溯+剪枝

回溯算法可以解决的问题

组合问题:N个数里面按一定规则找出k个数的集合
切割问题:一个字符串按一定规则有几种切割方式
子集问题:一个N个数的集合里有多少符合条件的子集
排列问题:N个数按一定规则全排列,有几种排列方式
棋盘问题:N皇后,解数独等等

回溯模板

Leetcode 77.组合

在这里插入图片描述

---------------🎈🎈题目链接🎈🎈-------------------

解法1 回溯法三部曲,函数参数、终止条件和单层搜索逻辑

在这里插入图片描述

class Solution {
    List<List<Integer>> result = new ArrayList<>();  // 用于汇总单一结果作为最终结果
    List<Integer> path = new ArrayList<>();    // 用于存放符合条件单一结果

    public List<List<Integer>> combine(int n, int k) {
        backtracking(n,k,1);
        return result;
    }
    public void backtracking(int n, int k, int startindex){ // 1.确定递归函数的参数和返回值
        // 2.确定终止条件:当最后得到的path的大小等于k 就可以将path存入result中了 终止递归
        // 注意一下!!这里把path存进result的时候,不能直接存path,不然就是浅拷贝,最后result中的值都一样
        if(path.size() == k){
            result.add(new ArrayList<>(path));
            return;
        }

        // 3. 确定横向的单层搜索逻辑 每次搜索都是从startindex开始,startindex保证取过不再取 保证【组合】
        // for循环用来横向遍历,从左到右取数 取过的数字不再取。递归的过程是纵向遍历,下一层搜索要从i+1开始。
        // 这里i<=n是因为 数据是范围 [1, n],i就代表了数据,而不是索引
        
        for(int i = startindex; i <= n; i++){ // 控制树的横向遍历
            path.add(i);  // 处理节点:将i加入到path路径中
            backtracking(n,k,i+1); // 递归:控制树的纵向遍历,注意下一层搜索要从startindex = i+1开始
            path.removeLast(); // 回溯,撤销处理的节点
        }

    } 
}  

注意事项 ⭐️
注意浅拷贝和深拷贝:使用new ArrayList<>(path)
注意移除ArrayList的最后一个元素方法: path.removeLast()

时间复杂度:分析回溯问题的时间复杂度,有一个通用公式:路径长度×搜索树的叶子数。对于本题它等于 O(k⋅C(n,k))

对于给定的n个元素,从中选择k个元素的组合数是C(n, k)。每个组合的平均长度是k(即组合中有k个元素),
在这里插入图片描述

空间复杂度:O(k),递归调用栈最大深度为k(k为要生成的组合的长度)


解法一plus 回溯法+剪枝

在这里插入图片描述

注意事项 ⭐️
注意浅拷贝和深拷贝:使用new ArrayList<>(path)
注意移除ArrayList的最后一个元素方法: path.removeLast()
剪枝优化if(n-(i-startindex)<k) continue; // 剪枝操作 自己写出来所有的变量,就知道了!!!要动手

class Solution {
    List<List<Integer>> result = new ArrayList<>();  // 用于汇总单一结果作为最终结果
    List<Integer> path = new ArrayList<>();    // 用于存放符合条件单一结果

    public List<List<Integer>> combine(int n, int k) {
        backtracking(n,k,1);
        return result;
    }
    public void backtracking(int n, int k, int startindex){ // 1.确定递归函数的参数和返回值
        // 2.确定终止条件:当最后得到的path的大小等于k 就可以将path存入result中了 终止递归
        // 注意一下这里把path存进result的时候,不能直接存path,不然就是浅拷贝,最后result中的值都一样
        if(path.size() == k){
            result.add(new ArrayList<>(path));
            return;
        }

        // 3. 确定横向的单层搜索逻辑 每次搜索都是从startindex开始,startindex保证取过不再取 保证【组合】
        // for循环用来横向遍历,从左到右取数 取过的数字不再取。递归的过程是纵向遍历,下一层搜索要从i+1开始。
        // 这里i<=n是因为 数据是范围 [1, n],i就代表了数据,而不是索引
       
        for(int i = startindex; i <= n; i++){ // 控制树的横向遍历
            if(n-(i-startindex)<k) continue;  // 剪枝操作!!!!!!!!!!!!!!!!!!!!!!!!!!
            path.add(i);  // 处理节点:将i加入到path路径中
            backtracking(n,k,i+1); // 递归:控制树的纵向遍历,注意下一层搜索要从startindex = i+1开始
            path.removeLast(); // 回溯,撤销处理的节点
        }

    } 
}



另一道组合回溯问题 216. 组合总和 III

相对于77. 组合 (opens new window),无非就是多了一个限制,本题是要找到和为n的k个数的组合,而整个集合已经是固定的了[1,…,9]。

本题k相当于树的深度,9(因为整个集合就是9个数)就是树的宽度。

例如 k = 2,n = 4的话,就是在集合[1,2,3,4,5,6,7,8,9]中求 k(个数) = 2, n(和) = 4的组合。
在这里插入图片描述

解法:回溯

遍历求加和sum,sum=n时,若递归深度为k,则将当前path加入result

if(sum == n){
	if(path.size() == k){
		result.add(new ArrayList<>(path));  // 注意新建ArrayList赋值!!!!!!
	}
	return; // 如果path.size() == k 但sum != targetSum 直接返回
}

之后进行回溯,sum回溯+path回溯

class Solution {
    List<List<Integer>> result = new ArrayList<>();
    List<Integer> path = new ArrayList<>();
    int sum = 0;
    public List<List<Integer>> combinationSum3(int k, int n) {
        backtracking(k,n,1);
        return result;
    }
    public void backtracking(int k, int n, int startindex){
        // 终止条件
        if(sum == n){
            if(path.size() == k){
                result.add(new ArrayList<>(path));
            }
            return;
        }

        for(int i = startindex; i <= 9; i++){
            path.add(i);
            sum += i;
            backtracking(k,n,i+1);
            sum -= path.get(path.size()-1);  // 回溯
            //sum -= i;  // 回溯 这个方法也行
            path.removeLast(); // 回溯
        }
    }
}

解法: 回溯+剪枝

在这里插入图片描述

class Solution {
    List<List<Integer>> result = new ArrayList<>();
    List<Integer> path = new ArrayList<>();
    int sum = 0;
    public List<List<Integer>> combinationSum3(int k, int n) {
        backtracking(k,n,1);
        return result;
    }
    public void backtracking(int k, int n, int startindex){
        // 终止条件
        if(sum >n) return;  // 剪枝 如果sum已经大于n了,那就return
        if(sum == n){
            if(path.size() == k){
                result.add(new ArrayList<>(path));
            }
            return;
        }

        for(int i = startindex; i <= 9; i++){
            path.add(i);
            sum += i;
            backtracking(k,n,i+1);
            sum -= i;  // 回溯
            path.removeLast(); //回溯
        }
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1490498.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C++设计模式之——享元模式详解和代码案例

文章目录 C中实现享元模式通常涉及以下几个关键部分&#xff1a;一个简单的C代码片段示例享元模式的进一步说明C享元模式代码案例——咖啡店订单系统享元模式在现实世界的应用场景 C中实现享元模式通常涉及以下几个关键部分&#xff1a; 享元模式&#xff08;Flyweight Patter…

【Linux网络】再谈 “协议“

目录 再谈 "协议" 结构化数据的传输 序列化和反序列化 网络版计算器 封装套接字操作 服务端代码 服务进程执行例程 启动网络版服务端 协议定制 客户端代码 代码测试 使用JSON进行序列化与反序列化 我们程序员写的一个个解决我们实际问题&#xff0c;满…

一手实测【Claude3】 - GPT4啊,你的时代终于要过去了

通过虚拟卡 WildCard 的方式来升级Claude3最快了&#xff0c;大概2分钟就可以开通完成, 而且升级 GPT 4.0 价钱也不贵&#xff0c;虚拟卡一年10美元&#xff0c;Claude3 每个月也才 20美元。如果你觉得Claude3对你可能有帮助&#xff0c;那就赶快来升级吧&#xff01; Claude3…

这本书太好了!150页就能让你上手大模型应用开发

如果问个问题&#xff1a;有哪些产品曾经创造了伟大的奇迹&#xff1f;ChatGPT 应该会当之无愧入选。仅仅发布 5 天&#xff0c;ChatGPT 就吸引了 100 万用户——当然&#xff0c;数据不是关键&#xff0c;关键是其背后的技术开启了新的 AI 狂潮&#xff0c;成为技术变革的点火…

多功能声学综合馆:革新解决气膜场馆噪音难题

近年来&#xff0c;气膜场馆在各类活动中的广泛应用带来了许多便利&#xff0c;但其内部噪音问题也一直困扰着人们。为了有效解决这一挑战&#xff0c;多功能声学综合馆崭露头角&#xff0c;通过创新的声学技术成为解决气膜场馆噪音问题的独特方案。 在这个嘈杂的世界中&#x…

第三篇【传奇开心果系列】Python的自动化办公库技术点案例示例:深度解读Pandas股票市场数据分析

传奇开心果博文系列 系列博文目录Python的自动化办公库技术点案例示例系列 博文目录前言一、Pandas进行股票市场数据分析常见步骤和示例代码1. 加载数据2. 数据清洗和准备3. 分析股票价格和交易量4. 财务数据分析 二、扩展思路介绍1. 技术指标分析2. 波动性分析3. 相关性分析4.…

MYSQL07高级_Hash结构、平衡二叉树、B树、B+树介绍

文章目录 ①. 全表遍历②. Hash结构③. 平衡二叉搜索树(AVL)④. B树⑤. B树⑥. 时间复杂度 选择的合理性 磁盘的I/O操作次数对索引的使用效率至关重要查找都是索引操作,一般来说索引非常大,尤其是关系型数据库,当数据量比较大的时候,索引的大小有可能几个G甚至更多,为了减少索引…

头像剪切上传

头像剪切上传 文章说明核心Api示例源码效果展示源码下载 文章说明 本文主要为了学习头像裁剪功能&#xff0c;以及熟悉canvas绘图和转文件的相关操作&#xff0c;参考教程&#xff08;Web渡一前端–图片裁剪上传原理&#xff09; 核心Api 主要就一个在canvas绘图的操作 context…

【触想智能】工业一体机刷卡应用知识分享

工业一体机刷卡技术是一种高效、稳定、安全的身份认证方式&#xff0c;具有广泛的应用场景和优势。在工业自动化控制、生产过程监测等领域&#xff0c;它已成为必不可少的设备之一。 一、工业一体机刷卡的原理:工业一体机刷卡的原理和普通的刷卡设备类似&#xff0c;都是通过读…

VS2022如何添加行号?(VS2022不显示行号解决方法)

VS2022不显示行号解决方法 VS2022是非常好用的工具&#xff0c;很多同学在初学C/C的时候&#xff0c;都会安装&#xff0c;默认安装好VS2022后&#xff0c;写代码时&#xff0c;在编辑框的窗口左边就有显示行号&#xff0c;如下图所示&#xff1a; 但是有些同学安装好后&#…

阿里云中小企业扶持权益

为企业提供云资源和技术服务&#xff0c;助力企业开启智能时代创业新范式。阿里云推出中小企业扶持权益 上云必备&#xff0c;助力企业长期低成本用云 一、ECS-经济型e实例、ECS u1实例活动规则 活动时间 2023年10月31日0点0分0秒至2026年3月31日23点59分59秒 活动对象 同时满…

GEE:使用Sigmoid激活函数对单波段图像进行变换(以NDVI为例)

作者:CSDN @ _养乐多_ 本文将介绍在 Google Earth Engine (GEE)平台上,对任意单波段影像进行 Sigmoid 变换的代码。并以对 NDVI 影像像素值的变换为例。 文章目录 一、Sigmoid激活函数1.1 什么是 Sigmoid 激活函数1.2 用到遥感图像上有什么用?二、代码链接三、完整代码一…

Tomcat概念、安装及相关文件介绍

目录 一、web技术 1、C/S架构与B/S架构 1.1 http协议与C/S架构 1.2 http协议与B/S架构 2、前端三大核心技术 2.1 HTML&#xff08;Hypertext Markup Language&#xff09; 2.2 css&#xff08;Cascading Style Sheets&#xff09; 2.3 JavaScript 3、同步和异步 4、…

吴恩达机器学习全课程笔记第七篇

目录 前言 P114-P120 推荐系统 协同过滤 均值归一化 协同过滤的tensorflow实现 查找相关项目 P121-P130 基于内容的过滤 强化学习 P131-P142 状态动作值函数定义 Bellman方程 随机环境 连续状态空间应用实例 前言 这是吴恩达机器学习笔记的第七篇&#xff0c;…

linux kernel物理内存概述(二)

目录 物理内存数据结构 设备数物理内存描述 物理内存映射 map_kernel map_mem zone数据结构 zone类型 物理内存数据结构 站在处理器角度&#xff0c;管理物理内存的最小单位是页面。使用page数据结构描述&#xff0c;通常默认大小4kB&#xff0c;采用mem_map[]数组来存…

(每日持续更新)jdk api之PipedWriter基础、应用、实战

博主18年的互联网软件开发经验&#xff0c;从一名程序员小白逐步成为了一名架构师&#xff0c;我想通过平台将经验分享给大家&#xff0c;因此博主每天会在各个大牛网站点赞量超高的博客等寻找该技术栈的资料结合自己的经验&#xff0c;晚上进行用心精简、整理、总结、定稿&…

合作的终极策略,竟如此有数学规律?《多Agent系统引论》第6章 多Agent交互 原文注释

6.0 前言 本文介绍一下多Agent交互过程中的一些概念&#xff0c;并且我保证能给你在人类社会中的工作生活学习带来启发。 6.1 效用和偏好 6.1.1 不知道什么是效用&#xff1f;那我告诉你什么是边际效应递减&#xff01; 想象一个人&#xff0c;他总资产只有1块钱&#xff0c;…

Vue前端+快速入门【详解】

目录 1.Vue概述 2. 快速入门 3. Vue指令 4.表格信息案例 5. 生命周期 1.Vue概述 1.MVVM思想 原始HTMLCSSJavaScript开发存在的问题&#xff1a;操作麻烦&#xff0c;耦合性强 为了实现html标签与数据的解耦&#xff0c;前端开发中提供了MVVM思想&#xff1a;即Model-Vi…

什么是 End-to-End 测试?

在使用 vue 的模板创建新项目的时候&#xff0c;有一个选项是问&#xff0c;是否添加“端到端”测试&#xff1f;说实在我不知道&#xff0c;而且三个选项一个都不认识。 ? Add an End-to-End Testing Solution? › - Use arrow-keys. Return to submit. ❯ NoCypressNigh…

QChart柱状图

//柱状图// 创建柱状图数据QBarSet *set0 new QBarSet("");*set0 << 1601 << 974 << 655 << 362;QBarSeries *series new QBarSeries();series->append(set0);set0->setColor(QColor("#F5834B"));// 创建柱状图QChart *ch…