二刷代码随想录|Java版|回溯算法1|回溯基础理论+组合问题

news2024/11/20 6:29:26

理论

写链表之类的真的很痛苦,赶紧跳到回溯!这次我想结合算法设计这本书,把java版写出来。放在第三部分吧。希望能够在研一完成这项工作!
从一刷总结以下的几个要点:

  1. 回溯方法模板性非常强!!可以解决绝大部分的问题。 (代码随想录的模板非常够用啦)!

  2. 回溯树很重要,要画得出来! (集合的大小就构成了树的宽度,递归的深度,都构成的树的深度。)以下是来自代码随想录的图!来自代码随想录

  3. 剪枝提高效率。

  4. 会涉及排序和组合(组合是不强调元素顺序的,排列是强调元素顺序。)。

  5. 会涉及到重复元素:层和树枝。

理论基础:设置递归函数实现穷举!
模版:常用的参数有(结束条件+解空间),startidx,used;全局的有path和res;函数内的有uset。

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

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

1.1 组合:N个数里面按一定规则找出k个数的集合(要用used)

1.2 分割:一个字符串按一定规则有几种切割方式(回文,个数要求,子串?)

1.3 子集:一个N个数的集合里有多少符合条件的子集(组合的子问题)

1.4 排列:N个数按一定规则全排列,有几种排列方式

1.5 棋盘问题:N皇后,解数独等等

1.6 其他

习题

2.1 组合问题

用到的全局变量:这要求熟练掌握ArrayList和List的相关操作,add(元素),remove(索引),size()。

    List<Integer> path  = new ArrayList<Integer>();
    List<List<Integer>> ans = new ArrayList<List<Integer>>();

再次注意,组合问题要有startidx!
关于StringBuilder的操作

\\Stringlength(), charAt
\\数组String[] numString = {"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};
StringBuilder path = new StringBuilder();\\初始化
path.append(str.charAt(i));\\增加元素
path.deleteCharAt(path.length() - 1);\\删除元素
ans.add(path.toString());\\转换为String

2.1.1 77. 组合

题目要求在1-n内找到所有可能的k个数的组合。
需要记一下一下代码的时间复杂度,O(n*2^n),目前还不知道怎么算。
代码随想录还给出了剪枝操作,讨论了n和k的关系,对于单次搜索的解空间大小,就是剩下的元素就算全部都枚举也不满足组合的个数要求要求,那么就结束。

for (int i = startIndex; i <= n - (k - path.size()) + 1; i++) // i为本次搜索的起始位置
class Solution {
    List<Integer> path  = new ArrayList<Integer>();
    List<List<Integer>> ans = new ArrayList<List<Integer>>();
    public void Backtracing(int k, int startIdx, int n) {
        if(path.size()==k){
            ans.add(new ArrayList<>(path));//注意拷贝
            return;
        }
        //组合是无顺序的,需要startidx
        for(int i=startIdx; i<=n; i++){
            path.add(i);
            Backtracing(k, i+1, n);
            path.remove(path.size()-1);
        }
    }
    public List<List<Integer>> combine(int n, int k) {
        path.clear();
        ans.clear();
        Backtracing(k, 1, n);
        return ans;
    }
}

2.1.2 17. 电话号码的字母组合

这题主要就是2-9个按钮,每个按钮有固定的字母,求给定的一串数字,能打出的所有字母组合。
这样数的深度就是数字的长度,每层的解空间就是数字对应的按钮的字母。
难点在字符串的操作。
Java要用到StringBuilder,因为path如果是String的类无法更改字符。

class Solution {
    String[] numString = {"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};
    StringBuilder path = new StringBuilder();
    List<String> ans = new ArrayList<>();
    public void BackTracing(int depth, String digits){
        if(depth==digits.length()){
            ans.add(path.toString());
            return;
        }
        String str = numString[digits.charAt(depth)-'0'];
        int width = str.length();
        for(int i=0; i<width; i++){
            path.append(str.charAt(i));
            BackTracing(depth+1, digits);
            path.deleteCharAt(path.length() - 1);
        }
    }
    public List<String> letterCombinations(String digits) {
        if (digits == null || digits.length() == 0) {
            return ans;
        }
        BackTracing(0, digits);
        return ans;     
    }
}

2.1.3 216. 组合总和 III

这题的题目要求是1-9个数字,要求枚举的组合满足:和为n,个数为k,无重复元素。(一般来说,要求越多越好剪枝,和就是一个天然的剪枝条件。)
增加全局变量sum。当然也可以作为一个函数参数。

class Solution {
    List<List<Integer>> ans = new ArrayList<List<Integer>>();
    List<Integer> path  = new ArrayList<Integer>();
    int sum=0;
    public void Backtracing(int k, int startIdx, int n) {
        if(path.size()==k&&sum==n){
            ans.add(new ArrayList<>(path));//注意拷贝
            return;
        }
        //组合是无顺序的,需要startidx
        for(int i=startIdx; i <= 9 - (k - path.size()) + 1; i++){
            if(sum+i>n){
                return;
            }
            path.add(i);
            sum += i;
            Backtracing(k, i+1, n);
            path.remove(path.size()-1);
            sum -= i;
        }
        
    }
    public List<List<Integer>> combinationSum3(int k, int n) {
        path.clear();
        ans.clear();
        Backtracing(k, 1, n);
        return ans;
    }
}

2.1.4 39. 组合总和

本题要求给的candidates,找到和为target的组合,candidates 中的 同一个 数字可以 无限制重复被选取 。
深度由target控制(剪枝也是,排序,剪枝),宽度是candidate的元素个数。所以我认为不用startIdx了。
但出现这种情况:
在这里插入图片描述
其实是要的,startIdx保证重复选取当前元素,而不重复选取之前的元素,从而避免上述问题。

// 来自代码随想录
class Solution {
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        List<List<Integer>> res = new ArrayList<>();
        Arrays.sort(candidates); // 先进行排序
        backtracking(res, new ArrayList<>(), candidates, target, 0, 0);
        return res;
    }

    public void backtracking(List<List<Integer>> res, List<Integer> path, int[] candidates, int target, int sum, int idx) {
        // 找到了数字和为 target 的组合
        if (sum == target) {
            res.add(new ArrayList<>(path));
            return;
        }

        for (int i = idx; i < candidates.length; i++) {
            // 如果 sum + candidates[i] > target 就终止遍历
            if (sum + candidates[i] > target) break;
            path.add(candidates[i]);
            backtracking(res, path, candidates, target, sum + candidates[i], i);
            path.remove(path.size() - 1); // 回溯,移除路径 path 最后一个元素
        }
    }
}

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

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

相关文章

redis报错:WRONGTYPE Operation against a key holding the wrong kind of value

这个是在redis存取的数据时&#xff0c;存数据时的数据类型和取数据时的数据类型不一致导致的 原因分析 首先需要明白的是&#xff0c;出现这种错误的原因是因为我们在取值的时候&#xff0c;使用的命令不对&#xff0c;比如你用获取string类型的get命令去取列表list类…

前端工程化之上cdn

一、cdn介绍 cdn的使用还是和前端打包相关&#xff0c;我们都希望前端最后的打包页面越小越好。那么可不可以把一些包不pack进去&#xff0c;让用户的流浪器自行下载呢&#xff1f;答案是可以的&#xff0c;那这些包就会被托管到分发站点上&#xff0c;就是在全国都有服务器&a…

Vue3探索编辑部——关于Pinia(1)

目录 什么是Pinia&#xff1f; Vue3中的Pinia 创建项目 数据准备和引入Pinia 使用Pinia 采用action修改数据 总结 什么是Pinia&#xff1f; Pinia是Vue3的专属的状态管理工具&#xff0c;什么是状态呢&#xff1f;其实我们可以把状态理解为数据&#xff0c;或者一个业务…

(七)for循环控制

文章目录 用法while的用法for的用法两者之间的联系可以相互等价用for改写while示例for和while的死循环怎么写for循环见怪不怪表达式1省略第一.三个表达式省略&#xff08;for 改 while&#xff09;全省略即死循环&#xff08;上面已介绍&#xff09; 用法 类比学习while语句 …

Linux:命名管道及其实现原理

文章目录 命名管道指令级命名管道代码级命名管道 本篇要引入的内容是命名管道 命名管道 前面的总结中已经搞定了匿名管道&#xff0c;但是匿名管道有一个很严重的问题&#xff0c;它只允许具有血缘关系的进程进行通信&#xff0c;那如果是两个不相关的进程进行通信&#xff0…

C#,计算几何,二维贝塞尔拟合曲线(Bézier Curve)参数点的计算代码

Pierre Bzier Bzier 算法用于曲线的拟合与插值。 插值是一个或一组函数计算的数值完全经过给定的点。 拟合是一个或一组函数计算的数值尽量路过给定的点。 这里给出 二维 Bzier 曲线拟合的参数点计算代码。 区别于另外一种读音接近的贝塞耳插值算法&#xff08;Bessels int…

市场复盘总结 20240123

仅用于记录当天的市场情况&#xff0c;用于统计交易策略的适用情况&#xff0c;以便程序回测 短线核心&#xff1a;不参与任何级别的调整&#xff0c;采用龙空龙模式 一支股票&#xff0c;只有10%的时间是可以操作&#xff0c;90%的时候都应该空仓 昨日主题投资 连板进级率 7/1…

前端实现转盘抽奖 - 使用 lucky-canvas 插件

目录 需求背景需求实现实现过程图片示意实现代码 页面效果lucky-canvas 插件官方文档 需求背景 要求实现转盘转动抽奖的功能&#xff1a; 只有正确率大于等于 80% 才可以进行抽奖&#xff1b;“谢谢参与”概率为 90%&#xff0c;“恭喜中奖”概率为 10%&#xff1b; 需求实现 实…

鸿蒙入门学习的一些总结

前言 刚开始接触鸿蒙是从2023年开始的&#xff0c;当时公司在调研鸿蒙开发板能否在实际项目中使用。我们当时使用的是OpenHarmony的&#xff0c;基于DAYU/rk3568开发板&#xff0c;最开始系统是3.2的&#xff0c;API最高是API9&#xff0c;DevecoStudio 版本3.1的。 鸿…

国考省考行测:分析推理,形式逻辑,所有有的分析

国考省考行测&#xff1a; 2022找工作是学历、能力和运气的超强结合体! 公务员特招重点就是专业技能&#xff0c;附带行测和申论&#xff0c;而常规国考省考最重要的还是申论和行测&#xff0c;所以大家认真准备吧&#xff0c;我讲一起屡屡申论和行测的重要知识点 遇到寒冬&am…

2024三掌柜赠书活动第七期:一本书读懂AIGC:探索AI商业化新时代

目录 前言AI商业化的背景和挑战关于《一本书读懂AIGC&#xff1a;探索AI商业化新时代》编辑推荐内容简介作者简介图书目录书中前言/序言《一本书读懂AIGC&#xff1a;探索AI商业化新时代》全书速览结束语 前言 不用多讲&#xff0c;想必大家也都知道&#xff0c;人工智能在过…

LLM大语言模型(五):用streamlit开发LLM应用

目录 背景准备工作切记streamlit开发LLM demo开一个新页面初始化session先渲染历史消息接收用户输入模拟调用LLM 参考 背景 Streamlit是一个开源Python库&#xff0c;可以轻松创建和共享用于机器学习和数据科学的漂亮的自定义web应用程序&#xff0c;用户可以在几分钟内构建一…

optee编译调试

编译运行 使用的是 ubuntu22.04 需要提前设置好网络 optee运行环境搭建&#xff1a;https://optee.readthedocs.io/en/latest/building/prerequisites.html 安装必要的库 sudo apt install -y \adb \acpica-tools \autoconf \automake \bc \bison \build-essential \ccach…

MySQL十部曲之六:数据操作语句(DML)

文章目录 前言语法约定DELETEINSERTSELECT查询列表SELECT 选项子句FROMWHEREORDER BYGROUP BYHAVINGWINDOWLIMITFOR SELECT ... INTO连接查询CROSS JOIN和INNER JOINON和USINGOUTER JOINNATURE JOIN 子查询标量子查询使用子查询进行比较带有ANY、IN或SOME的子查询带有ALL的子查…

C++ //练习 3.5 编写一段程序从标准输入中读入多个字符串并将它们连接在一起,输出连接成的大字符串。然后修改上述程序,用空格把输入的多个字符串分隔开来。

C Primer&#xff08;第5版&#xff09; 练习 3.5 练习 3.5 编写一段程序从标准输入中读入多个字符串并将它们连接在一起&#xff0c;输出连接成的大字符串。然后修改上述程序&#xff0c;用空格把输入的多个字符串分隔开来。 环境&#xff1a;Linux Ubuntu&#xff08;云服务…

网络安全B模块(笔记详解)- 越权与下载

1.使用渗透机场景kali中工具扫描服务器场景&#xff0c;将web端口号当作Flag提交&#xff1b; 2.使用渗透机场景windows7访问服务器场景mingling.php,将页面中的Flag提交&#xff1b; 3.使用渗透机场景windows7访问服务器场景mingling.php&#xff0c;分析页面内容&#xff0…

SpringBoot引入 liteflow 规则引擎,yyds!

1前言 在日常的开发过程中&#xff0c;经常会遇到一些串行或者并行的业务流程问题&#xff0c;而业务之间不必存在相关性。 在这样的场景下&#xff0c;使用策略和模板模式的结合可以很好的解决这个问题&#xff0c;但是使用编码的方式会使得文件太多,在业务的部分环节可以这…

Apache Shiro <= 1.2.4反序列化漏洞攻击 CVE-2016-4437 已亲自复现

Apache Shiro < 1.2.4反序列化漏洞攻击 CVE-2016-4437 已亲自复现 漏洞名称漏洞描述影响版本 漏洞复现环境搭建漏洞利用 修复建议总结 漏洞名称 漏洞描述 在 1.2.5 之前的 Apache Shiro 中&#xff0c;当未为“记住我”功能配置密钥时&#xff0c;远程攻击者可以通过未指定…

去创造,不要消费

最近&#xff0c;想必许多人的社交圈&#xff0c;都被B站的五四视频《后浪》刷屏了。 如果你没看过&#xff0c;也没关系&#xff0c;因为我并不打算讲它。 &#xff08;熟悉我的老读者会知道&#xff0c;我文章最开头的东西一般只是个引子&#xff0c;并不重要&#xff09; 言…

Peter算法小课堂—二叉堆(优先队列)

课前小视频&#xff1a;(7 封私信 / 62 条消息) 看动画&#xff0c;学算法&#xff0c;C实现建立二叉堆&#xff0c;优先队列和堆排序的基础 - 知乎 (zhihu.com) 二叉堆&#xff08;优先队列&#xff09; 大家想想&#xff0c;什么数据结构能做到插入&#xff08;删除&#x…