C++算法 —— 回溯(二)

news2025/1/20 2:37:33

一、字母大小写全排列

1.链接

784. 字母大小写全排列 - 力扣(LeetCode)

2.描述

3.思路

首先,根据题意,这是一个不能重复的全排列,并且根据特定的规则,我们需要分三种情况,一种是当字符为数字时,则直接往下递归,为字母时,大小写分别递归,并且回溯

代码设计:

全局变量:path 、 ret 

函数头:void dfs(string s,int pos)

剪枝:实际就是根据要求对字符进行分类递归即可

借用一下库里关于判断字符类型和大小写转化的函数,实际实现也不难

4.参考代码

class Solution {
    string path;
    vector<string> ret; 
public:
    vector<string> letterCasePermutation(string s) 
    {
        dfs(s,0);
        return ret;
    }
    void dfs(string s,int pos)
    {
        if(path.size() == s.size())
        {
            ret.push_back(path);
            return;
        }
        if(isdigit(s[pos]))//数字
        {
            path+=s[pos];
            dfs(s,pos+1);
            path.pop_back();
        }
        if(isalpha(s[pos]))
        {
            char tmp = tolower(s[pos]); //小写
            path+=tmp;
            dfs(s,pos+1);
            path.pop_back();

            tmp = toupper(s[pos]);//大写
            path+=tmp;
            dfs(s,pos+1);
            path.pop_back();
        }
    }
};

二、优美的排列

1.链接

526. 优美的排列 - 力扣(LeetCode)

2.描述

3.思路

一共有n个位置,每个位置要求不重复且无序的进行全排列,因此我们采用的bool数组的方式去进行剪枝,这里不要求返回数组,只要求记录符合要求的个数,因此,不需要path数组记录,而是直接带一个参数下标pos去表示,当前选择到第几个位置,只选择符合要求的路径,最后直到pos到达n+1时,意味着该路径是符合题意的,ret++;

4.参考代码

class Solution {
    int count = 0;
    bool cheak[16] = {false};
public:
    int countArrangement(int n) 
    {
        dfs(n,1);
        return count;
    }
    void dfs(int n,int pos)
    {
        if(pos == n+1)
        {
            count++;
            return;
        }

        for(int i = 1;i<=n;i++)
        {
            if(cheak[i] == false && (i%pos == 0 || pos%i == 0) )
            {
                cheak[i] = true;
                dfs(n,pos+1);
                cheak[i] = false;
            }
        }
    }
};

三、N皇后

1.链接

51. N 皇后 - 力扣(LeetCode)

2.描述

3.思路

4.参考代码

class Solution {
    vector<vector<string>> ret;
    vector<string> path;
    int aim = 0;
    bool cheak_col[10] = {false};
    bool cheak_dig1[20] = {false};
    bool cheak_dig2[20] = {false};
public:
    vector<vector<string>> solveNQueens(int n) 
    {
        vector<string> tmp(n,string(n,'.'));
        path = tmp;
        aim = n;
        dfs(0);
        return ret;
    }
    void dfs(int row)
    {
        if(row == aim)
        {
            ret.push_back(path);
            return;
        }

        for(int col =0;col<aim;col++)
        {
            if(!cheak_col[col] && !cheak_dig1[row-col+aim] && !cheak_dig2[row+col])
            {
                path[row][col] = 'Q';
                cheak_col[col] = true;
                cheak_dig1[row-col+aim] = true;
                cheak_dig2[row+col] = true;

                dfs(row+1);

                path[row][col] = '.';
                cheak_col[col] = false;
                cheak_dig1[row-col+aim] = false;
                cheak_dig2[row+col] = false;
            }
        }
    }
};

四、有效的数独

1.链接

36. 有效的数独 - 力扣(LeetCode)

2.描述

3.思路

本题是为了给下一题的剪枝思考做铺垫,该题的思路就是如何判断一个数独合法

首先是当前列和行不能出现相同的数字,可以使用一个二维的bool数组,第一个[ ]内记录行(列)数,第二个[ ] 记录数字n

bool row[9][10] 

bool col[9][10]

然后是每一个3*3的小区域,可以使用一个三维的数组,前两个格子锁定哪一块区域,最后一个格子记录数字

bool reg[3][3][10]

4.参考代码

class Solution 
{
    bool row[9][10] = {false};
    bool col[9][10] = {false};
    bool reg[3][3][10] = {false};
public:
    bool isValidSudoku(vector<vector<char>>& board) 
    {
        for(int i = 0;i<9;i++)
        {
            for(int j = 0;j<9;j++)
            {
                char ch = board[i][j];
                if(ch!='.' && (row[i][ch-'0'] || col[j][ch-'0'] || reg[i/3][j/3][ch-'0']))
                    return false;
                if(ch != '.')
                {
                    row[i][ch-'0'] = true;
                    col[j][ch-'0'] = true;
                    reg[i/3][j/3][ch-'0'] = true;
                }
            }
        }
        return true;
    }
};

五、解数独

1.链接

37. 解数独 - 力扣(LeetCode)

2.描述

3.思路

这题的剪枝策略和上题的思路是一样的,就是利用那三个bool数组去实现剪枝策略,首先要先记录下题目给的数据,将有数字的部分先记录true,然后就是关于dfs的设计了,我们可以将棋盘进行每个格子逐个去递归向下,每一个格子去尝试1到9的数字,当有一个格子1到9都不能合法时,意味着前面的某个数字虽然局部合法,但并非整体的解,因此需要告诉上一层数字选择不合理,就需要一个bool返回值,此外,当某次尝试成功时,不需要回溯,直接告诉上一层不需要继续尝试,直接返回结果即可,当所有值遍历完成后得到最终解返回true

这题的难点在于理解返回值的设置,这里会结合代码进行分析

4.参考代码

class Solution {
    bool row[9][10] = {false};
    bool col[9][10] = {false};
    bool reg[3][3][10] = {false};
public:
    void solveSudoku(vector<vector<char>>& board) 
    {
        for(int i = 0;i<9;i++)//记录棋盘
        {
            for(int j = 0;j<9;j++)
            {
                char ch = board[i][j];
                if(ch != '.')
                {
                    int num = ch - '0';
                    row[i][num] = col[j][num] = reg[i/3][j/3][num] = true;
                }
            }
        }
        dfs(board);
    }
    bool dfs(vector<vector<char>>& board)
    {
        for(int i = 0;i<9;i++)
        {
            for(int j = 0;j<9;j++)
            {
                char ch = board[i][j];
                if(ch == '.')
                {
                    for(int num = 1;num<=9;num++)
                    {
                        if(!row[i][num] && !col[j][num] && !reg[i/3][j/3][num])
                        {
                            board[i][j] = '0'+num;
                            row[i][num] = col[j][num] = reg[i/3][j/3][num] = true;
                            if(dfs(board) == true) return true;
                            board[i][j] = '.';
                            row[i][num] = col[j][num] = reg[i/3][j/3][num] = false;
                        }
                    }
                    return false;
                }

            }
        }
        return true;
    }
};

5.代码分析

总结

本章继续总结了经典dfs的题目,其中较为难的部分是根据题目的剪枝策略的思考,下一章会继续总结dfs关于二维中的深度搜索

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

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

相关文章

Android源码解析之截屏事件流程

今天这篇文章我们主要讲一下Android系统中的截屏事件处理流程。用过android系统手机的同学应该都知道&#xff0c;一般的android手机按下音量减少键和电源按键就会触发截屏事件&#xff08;国内定制机做个修改的这里就不做考虑了&#xff09;。那么这里的截屏事件是如何触发的呢…

基于spring boot的班级综合测评管理系统

基于spring boot的班级综合测评管理系统设计与实现 开发语言&#xff1a;Java 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09; 数据库工具&#xff1a;Navicat11 开…

Linux进阶篇:linux操作系统一个神奇的分区:swap交换分区

linux操作系统一个神奇的分区&#xff1a;swap交换分区 1 Swap交换分区概念 Linux内核为了提高读写效率与速度&#xff0c;会将文件在内存中进行缓存&#xff0c;这部分内存就是Cache Memory(缓存内存)。即使你的程序运行结束后&#xff0c;Cache Memory也不会自动释放。这就…

微信小程序 django+nodejs电影院票务售票选座系统324kd

小程序Android端运行软件 微信开发者工具/hbuiderx uni-app框架&#xff1a;使用Vue.js开发跨平台应用的前端框架&#xff0c;编写一套代码&#xff0c;可编译到Android、小程序等平台。 前端&#xff1a;HTML5,CSS3 VUE 后端&#xff1a;java(springbootssm)/python(flaskdja…

网盘——显示在线用户

1、查看在线用户 客户端发送查看请求&#xff08;只发送用户的名字&#xff09;&#xff0c;服务器将数据库中在线的用户查询出来并发送给客户端&#xff0c;客户端接收在线用户信息并作显示。 1.1、查看数据库的数据&#xff0c;在这里需要使用socket&#xff0c;所以我们在…

springboot相关报错解决

Caused by: java.lang.ClassNotFoundException: 目录 Caused by: java.lang.ClassNotFoundException: org.springframework.context.event.GenericApplicationListener spring-boot-dependencies:jar:2.1.9.RELEASE was not found org.springframework.context.event.Generi…

界面设计【1】-项目的UI设计css

引言&#xff1a; 本篇博客对简单的css html界面设计做了简要介绍 这篇博客主要就是介绍了做横向项目中&#xff0c;CSS界面设计与优化。 界面设计【1】-项目的UI设计css 1. 什么是css?2. css编程demo3. 可视化效果 1. 什么是css? CSS是层叠样式表&#xff08;Cascading S…

大型语言模型有什么用?

大型语言模型有什么用&#xff1f; 大型语言模型识别、总结、翻译、预测、生成文本和其他内容。 AI 应用程序正在总结文章、撰写故事和进行长时间对话——而大型语言模型正在承担繁重的工作。 大型语言模型或 LLM 是一种深度学习算法&#xff0c;可以根据从海量数据集中获得…

【PHP程序设计(高阶版)】——PHP操作MySQL教程

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;开发者-曼亿点 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 曼亿点 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a…

Linux C应用编程:MQTT物联网

1 MQTT通信协议 MQTT&#xff08;Message Queuing Telemetry Transport&#xff0c;消息队列遥测传 输&#xff09;是一种基于客户端-服务端架构的消息传输协议&#xff0c;如今&#xff0c;MQTT 成为了最受欢迎的物联网协议&#xff0c;已广泛应用于车联网、智能家居、即时聊…

TikTok怎么开通ads账户

一、TikTok的两种主流玩法 1、付费流量 蓝V认证TikTokAds&#xff08;广告消耗达到3w美金可申请蓝V认证&#xff09; 可以快速引流到独立站 2、免费流量 自己运营种草号、开直播 二、TikTok Ads如何开户&#xff1f; 开通广告账户 首先国内是无法自己申请TikTok Ads的&a…

精彩回顾 | 「AI 驱动增长,研发数智化升级」分享沙龙成功举办

AI 应用元年&#xff0c;人工智能技术将如何助力企业发展新质生产力&#xff0c;构建增长动能&#xff1f; 日前&#xff0c;LigaAI 与深圳市企业联合会、西云数据联合举办了「AI 驱动增长&#xff0c;研发数智化升级」技术专题沙龙。本次活动围绕「AI」应用实践&#xff0c;邀…

【QingHub】EMQX单节点一键部署

EMQX 简介 EMQX是全球最具扩展性的开源MQTT 代理&#xff0c;具有高性能&#xff0c;可在 1 个集群中连接 1 亿多个 IoT 设备&#xff0c;同时保持每秒 100 万条消息的吞吐量和亚毫秒级的延迟。 EMQX 支持MQTT、HTTP、QUIC、WebSocket等多种开放标准协议。它 100% 符合MQTT 5.…

电商技术揭秘十九:电商平台的智能化与自动化技术

相关系列文章 电商技术揭秘一&#xff1a;电商架构设计与核心技术 电商技术揭秘二&#xff1a;电商平台推荐系统的实现与优化 电商技术揭秘三&#xff1a;电商平台的支付与结算系统 电商技术揭秘四&#xff1a;电商平台的物流管理系统 电商技术揭秘五&#xff1a;电商平台…

Spring Web MVC的入门学习(二)

本篇接着Spring Web MVC的入门学习&#xff08;一&#xff09;-CSDN博客来继续学习Spring MVC。 一、从请求中获取Header 1、传统获取 header 获取Header也是从 HttpServletRequest 中获取。 代码&#xff1a; import jakarta.servlet.http.HttpServletRequest; import jakar…

社交网络的未来图景:探索Facebook的发展趋势

随着科技的不断进步和社会的快速变迁&#xff0c;社交网络作为连接人与人之间的重要纽带&#xff0c;扮演着日益重要的角色。而在众多社交网络中&#xff0c;Facebook作为老牌巨头&#xff0c;一直在探索着新的发展路径&#xff0c;引领着社交网络的未来图景。本文将深入探索Fa…

linux学习:栈(汉诺塔游戏)

第一根上面套着 64 个圆的金片&#xff0c;最大的一个在底下&#xff0c;其余一个比一个小&#xff0c;依次叠上去&#xff0c;庙里的众僧不倦地 把它们一个个地从这根棒搬到另一根棒上&#xff0c;规定可利用中间的一根棒作为帮助&#xff0c;但每次只能 搬一个&#xff0c;而…

【vue】v-model 双向数据绑定

:value&#xff1a;单向数据绑定v-model&#xff1a;双向数据绑定 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0">…

Maven创建项目

目录 1.创建项目 2.从Maven Repository: Search/Browse/Explore (mvnrepository.com)链接&#xff0c;下载API 3.1.0 3.在main文件内创建webapp文件夹&#xff0c;再webapp文件夹内创建WEB-INF文件夹&#xff0c;在WEB-INF文件夹内创建web.xml 4.网络编程 5.打包 6.部署 …

Leetcode二十三题:合并K个升序链表【22/1000 python】

“合并K个升序链表”&#xff0c;这是一道中等难度的题目&#xff0c;经常出现在编程面试中。以下是该问题的详细描述、解题步骤、不同算法的比较、代码示例及其分析。 问题描述 给你一个链表数组&#xff0c;每个链表都已经按升序排列。 请你将所有链表合并到一个升序链表中…