搜索与回溯练习(一)

简介: 本篇简介总结了基于搜索与回溯算法的经典练习题及其解法,涵盖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;
    }
目录
相关文章
|
2月前
|
机器学习/深度学习 计算机视觉
让模型不再忽视少数类:MixUp、CutMix、Focal Loss三种技术解决数据不平衡问题
在机器学习应用中,数据集规模有限且类别分布不均(如医学影像中正类仅占5%)常导致模型偏向多数类,虽准确率高,但少数类识别效果差。本文探讨MixUp、CutMix和Focal Loss三种技术,分别从数据增强与损失函数角度提升小规模不平衡数据集上的模型表现。
234 27
让模型不再忽视少数类:MixUp、CutMix、Focal Loss三种技术解决数据不平衡问题
|
5月前
|
Java 数据库 网络架构
菜鸟之路Day36一一Web开发综合案例(部门管理)
本文详细记录了基于Spring Boot的Web开发综合案例——部门管理功能的实现过程。从环境搭建到功能开发,涵盖数据库表设计、Spring Boot项目创建、依赖引入、配置文件设置以及Mapper、Service、Controller的基础结构构建。文章重点讲解了查询、删除、新增和修改部门信息的业务逻辑实现,遵循RESTful规范设计接口,并通过统一响应结果类`Result`优化前后端交互体验。借助Spring的IoC容器管理与MyBatis的SQL映射,实现了高效的数据操作与业务处理,最终完成部门管理的全功能开发。
155 12
|
5月前
|
SQL 存储 关系型数据库
菜鸟之路Day29一一MySQL之DDL
本文《菜鸟之路Day29——MySQL之DDL》由作者blue于2025年5月2日撰写,主要介绍了MySQL中的数据定义语言(DDL)。文章详细讲解了DDL在数据库和表操作中的应用,包括数据库的查询、创建、使用与删除,以及表的创建、修改与删除。同时,文章还深入探讨了字段约束(如主键、外键、非空等)、常见数据类型(数值、字符串、日期时间类型)及表结构的查询与调整方法。通过示例代码,读者可以更好地理解并实践MySQL中DDL的相关操作。
209 11
|
5月前
|
SQL XML Java
菜鸟之路Day33一一Mybatis入门
本文是《菜鸟之路Day33——Mybatis入门》的教程,作者blue于2025年5月18日撰写。文章介绍了MyBatis作为一款优秀的持久层框架,如何简化JDBC开发。通过创建SpringBoot工程、数据库表`user`及实体类`User`,引入MyBatis依赖并配置数据库连接信息,使用注解方式编写SQL语句实现查询所有用户数据的功能。此外,还展示了如何通过Lombok优化实体类代码,减少冗余的getter/setter等方法,提高开发效率。最后通过单元测试验证功能的正确性。
213 19
|
5月前
|
关系型数据库 MySQL 程序员
菜鸟之路day31一一MySQL之多表设计
本文由blue撰写于2025年5月9日,主要介绍了MySQL多表设计的三种关系:一对多、一对一和多对多。一对多通过在“多”的一方添加关联字段实现,如部门与员工的关系;一对一通常用于单表拆分,通过唯一外键关联,例如学生与学生证的关系;多对多则需创建中间表,包含两个外键分别关联两方主键,如学生与课程的关系。文中还提供了实际案例,包括分类表、菜品表、套餐表及它们之间的关联设计,详细展示了多表设计的应用场景与实现方法。
165 14
|
6月前
|
前端开发 Java 程序员
菜鸟之路Day28一一分层解耦
本文《菜鸟之路Day28——分层解耦》由作者blue撰写于2025年4月29日,主要探讨软件开发中的三层架构与分层解耦概念。文章首先介绍了三层架构:Controller(控制层)、Service(业务逻辑层)和DAO(数据访问层),并深入讲解了“高内聚低耦合”的软件设计原则。接着,文章详细说明了控制反转(IOC)与依赖注入(DI)的实现方式,包括如何通过注解声明Bean对象、组件扫描以及解决多Bean冲突的方法(如@Primary、@Qualifier和@Resource)。内容结合实际开发场景,为初学者提供了清晰的指导。
198 15
|
6月前
|
存储 网络协议 API
Cpp网络编程Winsock API
本文详细介绍了使用Winsock API进行C++网络编程的过程,通过具体实例实现了一个基于TCP协议的C/S架构通信demo。文章从服务端与客户端两方面展开,涵盖网络库初始化、套接字创建、绑定IP与端口、监听与连接、数据收发到关闭连接等关键步骤。重点解析了`WSAStartup`、`socket`、`bind`、`listen`、`accept`、`connect`、`send`和`recv`等函数的使用方法及注意事项,并对比了标准库与Winsock库在链接时的区别。适合初学者了解Winsock网络编程基础。
284 35
|
7月前
|
JavaScript 前端开发 应用服务中间件
菜鸟之路Day25一一前端工程化(二)
本文是《菜鸟之路Day25——前端工程化(二)》的详细记录,作者blue于2025年3月19日撰写。文章基于Vue框架,从零开始搭建前端页面并部署到Nginx服务器。主要内容包括:Element组件库快速入门、综合案例实现(布局设计、组件开发、Axios异步加载数据)、Vue路由配置及项目打包部署。通过实例演示了如何使用Element完成页面构建,配置路由实现页面切换,以及利用Nginx部署前端应用。适合初学者学习前端工程化的完整流程。
120 3
|
7月前
|
JSON JavaScript 前端开发
菜鸟之路Day23一一JavaScript 入门
本文介绍了 JavaScript 的基础内容,包括 JS 的引入方式、基础语法、数据类型、运算符、类型转换、函数、对象(如 Array、String、自定义对象、JSON、BOM 和 DOM)、事件监听,以及 Vue 框架的初步使用。重点讲解了内部和外部脚本的引入、变量声明(var、let、const)、常见输出语句、数组与字符串的操作方法、DOM 操作及事件绑定,并通过实例展示了 Vue 的双向数据绑定和常用指令(v-bind、v-model、v-on、v-if、v-for 等)。
182 7
vscode——如何将终端调整到右侧
vscode——如何将终端调整到右侧
278 1