搜索与回溯练习(一)

简介: 本篇简介总结了基于搜索与回溯算法的经典练习题及其解法,涵盖LeetCode上的多道题目。内容包括组合问题(如77. 组合、216. 组合总和III)、电话号码字母组合(17. 电话号码的字母组合)、组合总和问题(39. 组合总和、40. 组合总和II)、分割回文串(131. 分割回文串)以及复原IP地址(93. 复原IP地址)。通过递归与剪枝技巧,解决了包含重复元素、多个集合选取、字符串处理等复杂场景下的组合与排列问题,强调了不降原则和去重方法的应用。代码示例详细展示了每种问题的解决思路,帮助读者深入理解回溯算法的核心思想。

搜索与回溯练习(一)

文章内容学习自代码随想录,感谢carl!!!!

77. 组合 - 力扣(LeetCode)

不降原则处理组合数问题

vector<vector<int>> ans;
    vector<int> path;
    void dfs(int n,int k,int start){
   
        if(path.size()==k){
   
            ans.push_back(path);
            return;
        }
        for(int i=start;i<=n-(k-path.size())+1;i++){
   //剪枝n-(k-path.size())+1,表示至多开始的位置,超过这个位置凑不到k个
            path.push_back(i);
            dfs(n,k,i+1);
            path.pop_back();
        }
    }
    vector<vector<int>> combine(int n, int k) {
   
        dfs(n,k,1);
        return ans;
    }

216. 组合总和 III - 力扣(LeetCode)

依然是不降原则处理组合数

vector<vector<int>> ans;
    vector<int> path;
    void dfs(int n,int k,int start,int sum){
   
        if(sum>n) return;//剪枝,如果sum,已经大于n了,那么就不用再找了,直接回溯
        if(path.size()==k){
   
            if(n==sum) ans.push_back(path);
            return;
        }
        for(int i=start;i<=9;i++){
   
            path.push_back(i);
            dfs(n,k,i+1,sum+i);
            path.pop_back();
        }
    }
    vector<vector<int>> combinationSum3(int k, int n) {
   
        dfs(n,k,1,0);
        return ans;
    }

以上两题都是在一个集合里面选取n个数,我们需要用一个start来标记,即利用不降原则挑选出不同的组合

17. 电话号码的字母组合 - 力扣(LeetCode)

本题是在多个集合里面选取,不需要标记开始位置来去重

string str[10]={
   " "," ","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};
    vector<string> ans;
    string path;
    void dfs(string digits,int step)
    {
   
        if(path.size()==digits.size()){
   
            ans.push_back(path);
            return;
        }
        string s=str[digits[step]-'0'];
        for(int i=0;i<s.size();i++){
   
            path+=s[i];
            dfs(digits,step+1);
            path.pop_back();
        }
    }
    vector<string> letterCombinations(string digits) {
   
        if(digits.size()==0) return ans;//空串的情况
        dfs(digits,0);
        return ans;
    }

39. 组合总和 - 力扣(LeetCode)

    vector<vector<int>> ans;
    vector<int> path;
    void dfs(vector<int>& candidates,int target,int sum,int start)
    {
   
        if(sum>target) return;
        if(sum==target){
   
            ans.push_back(path);
            return;
        }
        for(int i=start;i<candidates.size();i++){
   
                path.push_back(candidates[i]);
                dfs(candidates,target,sum+candidates[i],i);//注意此处的不降原则用i,不用i+1,表示这个数可以继续选
                path.pop_back();
        }
    }
    vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
   
        sort(candidates.begin(),candidates.end());
        dfs(candidates,target,0,0);
        return ans;
    }

以上这些题都是不包含重复元素的,那如果由重复元素我们又该怎么做呢?

40. 组合总和 II - 力扣(LeetCode)

像这道题他有重复的元素,却要求挑出来不能有重复的组合

vector<vector<int>> ans;
    vector<int> path;
    void dfs(vector<int>& candidates,int target,int sum,int start)
    {
   
        if(sum>target) return;
        if(sum==target){
   
            ans.push_back(path);
            return;
        }
        for(int i=start;i<candidates.size();i++){
   
            if(i>start&&candidates[i-1]==candidates[i]) continue;//如果本层搜索的首位和前一层相同则剪枝
            path.push_back(candidates[i]);
            dfs(candidates,target,sum+candidates[i],i+1);
            path.pop_back();
        }
    }
    vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
   
        sort(candidates.begin(),candidates.end());
        if(candidates[0]>target) return {
   };
        dfs(candidates,target,0,0);
        return ans;
    }

131. 分割回文串 - 力扣(LeetCode)

    vector<vector<string>> ans;
    vector<string> path;
    bool ishuiwen(string s,int sta,int end){
   
        while(sta<=end)
        {
   
            if(s[sta]==s[end]){
   
                sta++;
                end--;
            }
            else return false;
        }
        return true;
    }
    void dfs(string s,int start)
    {
   
        if(start==s.size()){
   
            ans.push_back(path);
            return;
        }
        for(int i=start;i<s.size();i++){
   
            if(ishuiwen(s,start,i)){
   
                string x=s.substr(start,i-start+1);
                path.push_back(x);
                dfs(s,i+1);
                path.pop_back(); 
            }
        }
    }
    vector<vector<string>> partition(string s) {
   
        dfs(s,0);
        return ans;
    }

93. 复原 IP 地址 - 力扣(LeetCode)

注意什么是非法的ip地址,数字大于255非法,数字开头为0也是非法的

vector<string> ans;
    bool isip(string s,int start,int end)
    {
   
        if(start>end) return false;
        if(s[start]=='0'&&start!=end) return false;
        int sum=0;
        for(int i=start;i<=end;i++){
   
            if(s[i]<'0'||s[i]>'9') return false;
            sum=sum*10+(s[i]-'0');
            if(sum>255) return false;
        }
        return true;
    }
    void dfs(string s,int start,int cnt,string path)
    {
   
        if(cnt==3){
   //cnt是拿来数点的个数的,数到3个
            if(isip(s,start,s.size()-1)){
   
                path+=s.substr(start,s.size()-start);
                ans.push_back(path);
            }
            return;
        }
        for(int i=start;i<s.size();i++){
   
            if(isip(s,start,i)){
   
                dfs(s,i+1,cnt+1,path+s.substr(start,i-start+1)+".");
            }
        }
    }
    vector<string> restoreIpAddresses(string s) {
   
        dfs(s,0,0,"");
        return ans;
    }
目录
相关文章
|
4月前
|
机器学习/深度学习 计算机视觉
让模型不再忽视少数类:MixUp、CutMix、Focal Loss三种技术解决数据不平衡问题
在机器学习应用中,数据集规模有限且类别分布不均(如医学影像中正类仅占5%)常导致模型偏向多数类,虽准确率高,但少数类识别效果差。本文探讨MixUp、CutMix和Focal Loss三种技术,分别从数据增强与损失函数角度提升小规模不平衡数据集上的模型表现。
335 27
让模型不再忽视少数类:MixUp、CutMix、Focal Loss三种技术解决数据不平衡问题
|
7月前
|
Java 数据库 网络架构
菜鸟之路Day36一一Web开发综合案例(部门管理)
本文详细记录了基于Spring Boot的Web开发综合案例——部门管理功能的实现过程。从环境搭建到功能开发,涵盖数据库表设计、Spring Boot项目创建、依赖引入、配置文件设置以及Mapper、Service、Controller的基础结构构建。文章重点讲解了查询、删除、新增和修改部门信息的业务逻辑实现,遵循RESTful规范设计接口,并通过统一响应结果类`Result`优化前后端交互体验。借助Spring的IoC容器管理与MyBatis的SQL映射,实现了高效的数据操作与业务处理,最终完成部门管理的全功能开发。
256 12
|
7月前
|
SQL Java 数据库连接
菜鸟之路Day34一一Mybatis-基础操作
本文介绍了MyBatis的基础操作,包括删除、插入、修改和查询功能的实现。通过`@Delete`、`@Insert`、`@Update`和`@Select`注解完成对应操作,支持主键自动生成与返回。同时探讨了`#{}`和`${}`的区别,前者用于预编译SQL提升安全性,后者直接拼接但存在SQL注入风险。文章还提供了根据ID查询及条件查询的示例,并介绍了实体类属性与数据库字段不一致时的解决方案,如使用驼峰命名规则或配置映射关系,确保数据封装准确。
224 32
|
6月前
|
XML SQL 前端开发
菜鸟之路Day37一一Web开发综合案例(员工管理)
本文介绍了基于Web开发的员工管理综合案例,涵盖分页查询、条件分页查询、删除员工和新增员工四大功能模块。通过前后端交互,前端传递参数(如页码、每页记录数、查询条件等),后端使用MyBatis与PageHelper插件处理数据查询与操作。代码结构清晰,包括Controller层接收请求、Service层业务逻辑处理以及Mapper层数据访问,并结合XML动态SQL实现灵活的条件查询。此外,新增与删除功能分别通过POST与DELETE请求完成,确保系统功能完整且高效。
210 7
|
6月前
|
存储 JSON 前端开发
菜鸟之路Day39一一登录
本文介绍了登录功能的实现及其相关技术细节,包括会话管理、令牌认证和异常处理等内容。作者通过 Java 实现了一个基于用户名和密码的登录接口,调用服务层和数据库层完成用户验证。同时,文章深入探讨了三种会话跟踪技术:Cookie、Session 和 JWT 令牌。 在 JWT 部分,详细讲解了其生成与校验流程,实现了登录成功后返回 JWT 令牌的功能。此外,文章还介绍了过滤器(Filter)和拦截器(Interceptor)的概念及应用,演示了如何利用它们实现登录校验。 最后,为解决前后端交互中异常响应不统一的问题,定义了一个全局异常处理器 将系统异常以统一的 JSON 格式返回给前端。
189 0
|
9月前
|
存储 Java 程序员
菜鸟之路Day26一一Maven
本文由blue撰写,发布于2025年3月25日,主要介绍Maven工具的使用。Maven是Apache旗下的开源项目,用于管理和构建Java项目,基于项目对象模型(POM)概念。文章详细讲解了Maven的安装配置、IDEA中集成Maven的方法、依赖管理(包括依赖配置、传递与排除、依赖范围)、以及Maven的生命周期(clean、default、site)。通过学习,读者可掌握Maven的基本功能及其在项目中的应用。
396 12
|
9月前
|
存储 网络协议 安全
Java网络编程,多线程,IO流综合小项目一一ChatBoxes
**项目介绍**:本项目实现了一个基于TCP协议的C/S架构控制台聊天室,支持局域网内多客户端同时聊天。用户需注册并登录,用户名唯一,密码格式为字母开头加纯数字。登录后可实时聊天,服务端负责验证用户信息并转发消息。 **项目亮点**: - **C/S架构**:客户端与服务端通过TCP连接通信。 - **多线程**:采用多线程处理多个客户端的并发请求,确保实时交互。 - **IO流**:使用BufferedReader和BufferedWriter进行数据传输,确保高效稳定的通信。 - **线程安全**:通过同步代码块和锁机制保证共享数据的安全性。
384 23
|
9月前
|
JavaScript 前端开发 应用服务中间件
菜鸟之路Day25一一前端工程化(二)
本文是《菜鸟之路Day25——前端工程化(二)》的详细记录,作者blue于2025年3月19日撰写。文章基于Vue框架,从零开始搭建前端页面并部署到Nginx服务器。主要内容包括:Element组件库快速入门、综合案例实现(布局设计、组件开发、Axios异步加载数据)、Vue路由配置及项目打包部署。通过实例演示了如何使用Element完成页面构建,配置路由实现页面切换,以及利用Nginx部署前端应用。适合初学者学习前端工程化的完整流程。
163 3
|
10月前
|
JSON Java 程序员
菜鸟之路Day17一一IO流(三)
本文主要介绍了Java中的打印流、压缩/解压缩流以及Commons-io和Hutool工具包的使用。打印流包括字节打印流(PrintStream)和字符打印流(PrintWriter),支持数据原样写出、自动刷新与换行。压缩/解压缩流通过ZipInputStream和ZipOutputStream实现文件和文件夹的压缩与解压。Commons-io和Hutool工具包提供了高效的IO操作方法,简化了文件复制、删除等常见任务。文中还展示了System.out.println()作为打印流的应用示例。
214 2
|
9月前
|
Java 程序员
菜鸟之路Day22一一反射与动态代理
本文介绍了Java反射机制和动态代理的基本概念及应用。反射允许编程访问类的成员变量、构造方法和成员方法,通过三种方式获取Class对象,并演示了如何使用反射创建对象、调用方法和修改字段值。动态代理则通过接口实现无侵入式功能增强,展示了如何利用`Proxy`类和`InvocationHandler`接口生成代理对象并拦截方法调用。结合实例代码,详细讲解了反射在实际开发中的应用场景,如保存对象信息到文件和根据配置文件动态创建对象。 反射的主要作用包括: 1. 获取类的所有信息。 2. 结合配置文件动态创建对象。 动态代理的核心优势在于能够在不修改原有代码的情况下,为对象添加额外功能。
174 0