【递归、搜索与回溯】综合练习三

综合练习三

  • 1.优美的排列
  • 3.N 皇后
  • 3.有效的数独
  • 4.解数独

在这里插入图片描述

点赞👍👍收藏🌟🌟关注💖💖
你的支持是对我最大的鼓励,我们一起努力吧!😃😃

1.优美的排列

题目链接:526. 优美的排列

题目描述:

在这里插入图片描述

注意一个数字只要能满足 perm[i] 能够被 i 整除 或者 i 能够被 perm[i] 整除,就是优美排列中的数字。

在这里插入图片描述
算法原理:
画出决策树,把所有情况不重不漏的找出来。
我们一个位置一个位置的去找,每个位置都有三种选择,但是要注意上一个位置选过的数下一个位置就不要选了。因此可以来一个全局bool 类型数组,记录每个数是否被选过。还有满足 perm[i] 能够被 i 整除 或者 i 能够被 perm[i] 整除 的数才能选。因为这里不需要统计每个组合是什么,我们也不需要path。而只需统计满足情况的有几种就行了。

在这里插入图片描述

class Solution {
    int ret;
    bool check[16];
public:
    int countArrangement(int n) {

        dfs(n,1);
        return ret;
    }

    void dfs(int n,int pos)
    {
        if(pos == n+1)
        {
            ++ret;
            return;
        }

        for(int i=1;i<=n;++i)
        {
            if(check[i] == false && (i%pos == 0 || pos%i == 0))
            {
                check[i]=true;
                dfs(n,pos+1);
                check[i]=false; //恢复现场
            }
        }
    }
};

3.N 皇后

题目链接:51. N 皇后

题目分析:

在这里插入图片描述

给一个n,代表的是n*n的棋盘,在这个棋盘上放皇后。按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。因此放皇后然后使皇后彼此之间不能相互攻击。问有几种解决方案?

算法原理:
这道题决策树还是比较好看画的,难的是如何剪枝+代码能力!
N皇后的决策树有两种画法,第一种比较麻烦,就是一个小格子一个小格子的来考虑能不能放。第二种就是考虑每次只考虑一行这个皇后应该放哪里。

每行都有n个位置可以放皇后,但是如果放皇后位置满足,皇后在一行或一列或者正对角线或者副对角线的,这个皇后就不能放!全局变量一个ret,一个path,回溯都和前面是一样的。递归函数,就是告诉我一个行数,我就尝试把每一个格子尝试放一个皇后,如果能放就放然后考虑下一行。dfs(row)。递归出口 row==n,说明遇到合法的情况,然后把path放到ret里。我们主要就说剪枝的情况。

在这里插入图片描述
接下来就是剪枝的情况了。
何剪枝:考虑当前这个位置,能否放上皇后?
有两种方法:
1.无脑循环。来四个循环,分别看同一行、同一列、主对角线、右对角线是否有皇后。有这个位置就不能放皇后,都没有就可以放皇后。
在这里插入图片描述
这里我们可以优化一下,没有必要四层循环,三层循环就够了。因为我们都一行一行的枚举,每一行要么第一列放,其他列不放。要么第二列放,其他列不放。要么第三列放,其他列不放。行决定不会出现相互攻击的情况,所有只用看看这一列,主对角线,副对角线有没有。

2.类似哈希表的策略
类似于五子棋那种常用的策略。仅用三个数组就可以搞定!
此时我判断某一列是否有皇后,可以搞一个bool类型大小为n的数组,bool col[n],就可以了。当在0列放一个皇后的时候,可以让col[0]=true, 说明这一列有皇后了。当到其他行的时候第一列就去看col[0]是否等于ture,等于true说明有皇后,不放就可以了。
在这里插入图片描述

接下来考虑主对角线和副对角线。我们把这几个位置抽象成几个点放到坐标系里。
主对角线不都是一条斜线吗,主对角线条数=2n-1, 这里是5条,我们就判断这5条对角线就可以了。我们这几条对角线的斜率都是1,因此所有线都可以用 y=x+b表示,此时移位就变成了 y-x=b,这个公式表达的意思是,就看这条红线,它上面的点用纵坐标减去横坐标是一个定值b ,因此继续**搞一个bool类型大小为2n的数组**,当我们发现y-x=b在数组里面是true的话,就说明这个对角线里面有皇后了。因为这个对角线里面y-x全都是一个定值。所以可以把这个定值放到数组下标里面,如果这个位置等于的true,表示这条对角线有皇后了,如果等于false,说明这条对角线没有皇后。
在这里插入图片描述
但是这里有一个问题,y-x这里是一个负数,在bool类数组下标里面是不存在负数的,没问题左右两边添加一个偏移量 y-x+n = b+n,通通向上平移n个单位。绝对是一个正数。因此我们求主对角线的时候,就是y-x+n去数组里面看看如果是true,有皇后。如果是false,没有皇后。
在这里插入图片描述
副对角线 斜率为-1, 那就是y=-x+b,此时移位 y+x=b,也就是这单单一条线里面,每一个点横坐标+纵坐标都是一个定值,所以我们又可以搞一个bool类型大小为2*n的数组。当我判断某个位置副对角线里面有没有皇后,我仅需拿这个位置的横纵坐标相加然后去数组找对应位置,如果是true,说明有皇后,如果是false,说明没有皇后。副对角线并不会出现负数的情况。因此只需要判断y+x在dig2是true还是false就行了。

在这里插入图片描述

class Solution {
    vector<vector<string>> ret;
    vector<string> path;
    bool checkCol[10],checkDig1[20],checkDig2[20];
    int _n;
public:
    vector<vector<string>> solveNQueens(int n) {
        _n=n;
        path.resize(n);
        for(int i=0;i<n;++i)
            path[i].resize(n,'.');

        dfs(0);
        return ret;   
    }

    void dfs(int row)
    {
        if(row == _n)
        {
            ret.push_back(path);
            return;
        }

        for(int col=0;col<_n;++col)
        {
            if(!checkCol[col] && !checkDig1[col-row+_n] && !checkDig2[col+row])
            {
                path[row][col]='Q';
                checkCol[col]=checkDig1[col-row+_n]=checkDig2[col+row]=true;
                dfs(row+1);
                checkCol[col]=checkDig1[col-row+_n]=checkDig2[col+row]=false;
                path[row][col]='.';
                
            }  
        }
    }
};

3.有效的数独

题目链接:36. 有效的数独

题目描述:

在这里插入图片描述

有效的数独,给一个9x9的格子,把数填满,其中每一行每一列以及3x3宫内,只能填1-9的数字,并且不能重复!

算法原理:
这里的思想和上面N皇后思想是一样的,采用类似哈希映射的方法。你让我判断一行有没有出现重复的元素,我可以搞一个bool类型的二维数组 bool row[9][10],前面9代表0~8行,后面多开一个空间 10个 里面有1~9的数字,row[3][7]=true 说明第三行7已经使用过了。
在这里插入图片描述
同理,这一列也搞一个bool 类型的二维数组,bool col[9][10],9代表0~8列,10代表有1 ~ 9,col[2][9]=true 代表第2列使用过9这个数字。

在这里插入图片描述
这个3x3的小格子,要么就是横着循环三次,竖着循环三次,但是这样太麻烦了。其实我们也可以搞一个哈希表把它存起来,让3行算作 一行,3列算作 一列。先搞出一个bool类型 bool grid[3][3] ,grid[0][0]代表第一个3x3的格子,grid[0][0]代表第二个3x3的格子,我们用3x3的数组就可以把所有小方格都表示出来了。然后我依旧要看每个3x3格子内数字是否重复,
在这里插入图片描述
因此再来一个10,搞成grid[0][0][10]的三维数组,来表示这里9个小方格,这里每个数映射到那个数组也非常好找,用这个数的下标/3,[x/3][y/3]就知道在那个小方格里了,然后10代表这个小方格里的1~9个数数字,grid[0][1][3] =true 表示第2个小放个里面3已经使用使用过了
在这里插入图片描述
因此我们就可以使用三个bool类型的数组,在O(1)的时间复杂度看一行一列一个小方格有没有出现重复数,这种就是典型的用空间换时间

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


    }
};

4.解数独

题目链接:37. 解数独

题目描述:

在这里插入图片描述

算法原理:
上面的是判断是否是有效数独,这里是填数独。这里还是用上面的三个bool类型数组,来判断这个数能不能放。这里我们一格一格的放,每个格子可以放1-9中其中一个数,但是肯定会是存在剪枝情况的。具体能不能放还是借助那三个bool类型数组来判断。我们递归就是拿着这个棋盘,开始依次遍历,看那个是空的就开始填,填的时候判断一下能填在填不能填就不填。然后能填递归到下一层,但是有可能这个能填的分支下面递归有的位置1 ~ 9都不能填的情况。因此这个分支可能是得不到正确结果的,那上面怎么知道你这种情况不行的呢?因此这个递归函数要有一个bool类型的返回值,当遇到某个格子1 ~ 9都不能填直接向上返回一个false,告诉它这个位置你填1不行,你要把这个位置填上2然后在往下试。递归函数参数只要把这个board给我就行了。bool dfs(board)

在这里插入图片描述

class Solution {
    bool row[9][10];
    bool col[9][10];
    bool grid[3][3][10];

public:
    void solveSudoku(vector<vector<char>>& board) {
        //初始化
        for(int i = 0; i < 9; ++i)
        {
            for(int j = 0; j < 9; ++j)
            {
           
               if(board[i][j] != '.')
               {
                    int num=board[i][j]-'0';
                    row[i][num]=col[j][num]=grid[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)
            {
               if(board[i][j] == '.')
               {
                    //填数
                    for(int num = 1; num <= 9; ++num)
                    {
                        if(!row[i][num] && !col[j][num] && !grid[i/3][j/3][num])
                        {
                            board[i][j]='0'+num;
                            row[i][num]=col[j][num]=grid[i/3][j/3][num]=true;
                            if(dfs(board) == true) return true; //这个位置填的数已经是最终结果了,不要再往下试了
                            //恢复现场
                            board[i][j]='.';
                            row[i][num]=col[j][num]=grid[i/3][j/3][num]=false;
                        }
                    }
                    return false; //某个位置1~9都不能选,返回false
               }
            }
        }
        return true; //已经把数填完了,没有空位置了,返回true
    }
};

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

用寄存器读取文件的数据的时候,寄存器怎么读取,寄存器的高位和低位分别是什么

如图所示 寄存器读取数据的时候&#xff0c;数据自身是什么样的&#xff0c;寄存器读的时候就原样存储在寄存器里&#xff0c;高位就是第一个数据&#xff0c;低位就是最后一个数据 寄存器读取数据原理是&#xff0c;将给定的二进制数反转&#xff0c;我理解成调转一下车头&…

驾驭未来:智能网关如何革新车联网体验

车联网&#xff08;Internet of Vehicles&#xff09;是一个跨领域的技术综合体&#xff0c;它基于物联网&#xff0c;利用先进的信息通信技术实现车与车、车与路、车与人、车与服务平台等的全方位网络连接。 龙兴物联智能网关是集成了多协议、多接口&#xff0c;具有综合数据采…

Three.js动效(第15辑):让前端手撕UI,拳打后端的效果。

three.js的设计效果非常复杂&#xff0c;后端提供的数据接口问题百出&#xff0c;这很容易让前端手撕UI、拳打后端&#xff0c;这种请详细该如何办呢&#xff1f; 前端 VS UI&#xff1a; 1. 沟通协调&#xff1a;UI和前端应该加强沟通&#xff0c;理解对方的工作难点和需求&…

「GitHub热点速览」7个学编程必看的开源项目!附链接可直达!

前言 今天特推的两个项目都是异常实用的项目&#xff0c;一个是直接将视频替换成另外一个语种&#xff1b;另外一个则是解决日志阅读问题的 tailspin&#xff0c;让你在成千上万条日志中快速定位特定的日志。 另外&#xff0c;还有两大集成者&#xff0c;一个是解决可观测性的…

去哪儿网PMO张璐受邀为第十三届中国PMO大会演讲嘉宾

全国PMO专业人士年度盛会 去哪儿网PMO张璐女士受邀为PMO评论主办的2024第十三届中国PMO大会演讲嘉宾&#xff0c;演讲议题为“数字化助力组织目标落地”。大会将于6月29-30日在北京举办&#xff0c;敬请关注&#xff01; 议题简要 本次议题将分享去哪儿流程标准化&工具化…

python17 字符串的常用操作

字符串常用方法 代码 字符串常用方法s i am SyLar, I LOVE YOU s1 s.capitalize()# 首字母变成大写 print(s1) s2s.lower() # 全部变成小写 print(s2) s3 s.upper()#全部变成大写 忽略大小写 推荐用这个 print(s3)title abc_def_hi print(标题:,title.title())s4 HelloWor…

2024年第三届数据统计与分析竞赛(A题)数学建模完整思路+完整代码全解全析

本次A题主要涉及正态分布、数据处理、自然语言处理等知识点 问题一题目重述&#xff1a;根据附件中抖音用户的评论数据&#xff0c;对抖音 APP 的“评分”和“点赞数”进行数据统计与分析&#xff0c;并使用假设检验判断这两个指标的分布是否服从正态分布。 接下来对问题一进…

2024南京人工智能展览会:推动南京地区人工智能产业快速发展

南京&#xff0c;作为长三角地区的一颗璀璨明珠&#xff0c;近年来在人工智能产业的发展上取得了举世瞩目的成绩。这座城市以其深厚的科技底蕴和前瞻的战略眼光&#xff0c;正逐步成为国内外人工智能技术研发和应用的重要基地。 近年来&#xff0c;随着人工智能技术的快速发展…

纷享销客PaaS平台基础能力:一文说清 “业务定制能力”

01、业务对象定制能力 一个优秀的PaaS(平台即服务)平台的业务对象定制能力应该具备以下特点&#xff1a; 敏捷的业务模型&#xff1a; 能够根据用户的业务需求&#xff0c;提供可定制的数据模型和数据处理能力&#xff0c;支持各种数据类型和数据操作。 可视化的界面定制能力…

Nature 苏浩团队发表创新人工智能“仿真中学习”框架,实现外骨骼的智能性和通用性

北京时间2024年6月12日23时&#xff0c;美国北卡罗来纳州立大学与北卡罗来纳大学教堂山分校的苏浩团队在《自然》&#xff08;Nature&#xff09;上发表了一篇关于机器人和人工智能算法相结合服务人类的突破性研究论文&#xff0c;标题为“Experiment-free Exoskeleton Assista…

股票交易系统

效果展示&#xff0c;如下动图&#xff1a; 首先简述一下股票交易规则&#xff1a; 买卖股票&#xff0c;股民可以自行选择股票的买入或卖出价格和股票的数量&#xff0c;但是用户不一定马上就交易成功&#xff0c;只有当股票价格低于买入价才有机会买入&#xff0c;高于卖出价…

MS1112驱动开发(iio框架)

作者简介&#xff1a; 一个平凡而乐于分享的小比特&#xff0c;中南民族大学通信工程专业研究生在读&#xff0c;研究方向无线联邦学习 擅长领域&#xff1a;驱动开发&#xff0c;嵌入式软件开发&#xff0c;BSP开发 作者主页&#xff1a;一个平凡而乐于分享的小比特的个人主页…

期货交易中的仓位管理

期货市场就像是一个复杂的游戏场所。由于期货高杠杆双向交易机制的影响&#xff0c;期货交易中错误的容忍度很低&#xff0c;所以期货交易系统中最重要的是风险控制。而风险控制体系最核心的是仓位管理&#xff0c;因为仓位的多少直接影响到潜在损失的大小。 仓位管理指的是账户…

做好程序前设计

不要小看任何一道编程题目&#xff01;一定一定一定要想好之后再动手&#xff01;&#xff01;&#xff01; 带上你的草稿本&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xf…

LLoCO技术:突破大型语言模型处理长文本的局限

在自然语言处理领域&#xff0c;大型语言模型&#xff08;LLMs&#xff09;虽然在众多任务上展现出了卓越的能力&#xff0c;但在处理长文本上下文时却遭遇了瓶颈。由于自注意力机制导致的计算和内存开销随序列长度呈二次方增长&#xff0c;使得这些模型在面对长文本时力不从心…

Vue3中的常见组件通信之`provide`、`inject`

Vue3中的常见组件通信之provide、inject 概述 ​ 在vue3中常见的组件通信有props、mitt、v-model、 r e f s 、 refs、 refs、parent、provide、inject、pinia、slot等。不同的组件关系用不同的传递方式。常见的撘配形式如下表所示。 组件关系传递方式父传子1. props2. v-mo…

大数据的力量:推动战略决策和业务转型

在当前全球化的时代背景下&#xff0c;国际间的联系日益紧密&#xff0c;世界变得更加互联互通。面对各种危机&#xff0c;数据驱动决策和分析显得愈发重要。从医学研究到市场趋势分析&#xff0c;大数据技术在各个领域发挥着关键作用&#xff0c;推动着一场深刻的变革浪潮。 大…

关于伪标头那些事

前言 看到伪标头&#xff0c;不少同学可能会比较陌生&#xff0c;因为谁让它默默无闻呢&#xff1f; 当然博主把它比喻为一个来自传输层的“共享盒子”。提到共享&#xff0c;我想大家有所体会了。这里给大家贴一张直观的图例&#xff0c;可以静静观摩之。 Q&#xff1a;什么是…

高端品牌网站建设

随着互联网的快速发展&#xff0c;越来越多的企业开始意识到高端品牌网站建设对于企业发展的重要性。高端品牌网站建设不仅是企业形象展示的窗口&#xff0c;更是与消费者进行有效沟通和互动的桥梁。下面从设计、内容和用户体验三个方面&#xff0c;探讨高端品牌网站建设的重要…

使用代理IP常见问题有哪些?

代理IP在互联网数据收集和业务开展中发挥着重要作用&#xff0c;它充当用户客户端和网站服务器之间的“屏障”&#xff0c;可以保护用户的真实IP地址&#xff0c;并允许用户通过不同的IP地址进行操作。然而&#xff0c;在使用代理IP的过程中&#xff0c;用户经常会遇到一些问题…