
本文共 3885 字,大约阅读时间需要 12 分钟。
目录
模拟
暴力
很多情况下分析题目可以确定一个数据的范围,所以我们可以直接使用for循环在这个范围中找到符合题目要求的答案即可。暴力枚举中每一个for循环都有自己表示的意义
对于这种尝试性的题目,使用for循环暴力枚举即可
尝试性的选择题都是可以使用暴力解决的,关键是如何找到合适的暴力策略
有的时候没有思路的时候举例子结合分析是一个不错的方法,往往在结合具体的例子的时候可以找出其中的规律
分析
递归
凡是搜索所有可能性的方案中并且从中找出最佳方案的问题都可以使用递归解决,可以使用递归求解出列表/集合中各个元素的所有排列组合方案,在递归求解的时候可以使用List/dict/str数据结构来记录中间的过程这样在递归出口的时候可以输出对应变量的值,并且使用List/dict序列、映射数据结构进行记录中间递归结果的时候一般在当前的递归方法调用完成之后需要回溯,也就是恢复到之前的状态然后尝试下一个可能的状态。对于数据规模较小的可以使用递归解决如果数据规模较大的使用递归解决就可会超时,有的时候根本就计算不出来结果,这个时候一般会在递归或者是暴力枚举的状态下进进行优化,一般使用动态规划中状态之间的转移的思路进行解决。递归中选择要是不要的两种平行状态的经典题目有:平方拆分、ABC、种树这几道经典的题目,两种平行状态的递归有两种写法,分别是在递归方法体中写两个递归方法与在for循环中进行递归
有的时候正向递归可能耗时大而且比较复杂,可以从结果出发进行递归一直到已知的初始条件为止
为了避免递归过程中数字出现顺序的不同被计算为不同的方案的时候那么可以从另外一种角度考虑问题,比如出现的次数等这样可以避免掉这个问题,这道题目对于理解递归求解的思路还是很有帮助的
搜索所有的可能性,在写递归方法的时候边写边传递需要的参数
下面的方格分割题目中从中心点开始两边四个方向的递归的思路还是挺不错的,值得学习学习,并且可以在剪的时候使用List[turple]以元组作为列表的元素记录下最终剪的方案
下面四阶幻方是一道按照一维列表元素下标在二维坐标中的进行编号,其中的思路还是挺不错的,可以应用到其他类似的二维矩阵中填数字满足行/l列/对角线满足某个关系的题目中,这样可以减少很多不满足条件往下的优化
下面的正则问题使用的是递归求解表达式的值,利用到了递归调用之后返回结果的特点来求解出表达值的值,可以避免某些for循环中 + if判断的麻烦操作
也可以调用python中的itertools模块中的permutations方法生成全排列
本质上是计算在x个元素中选择n个元素的组合方案
宽搜
宽搜一般借助于队列实现,一般都是几个固定的套路: a:声明一个队列,往队列中加入起始的节点,其中节点包含了当前节点所在的位置,节点中包含的路径等信息 b:当队列非空的时候执行循环,第一步是弹出队首节点(队列中最早加入的那个节点)判断位置是否满足最终题目要求的位置,如果满足那么结束整个循环,不满足继续往下执行 c:当弹出的当前节点不满足题目要求的最终位置的时候这个时候就需要加入周围可以到达的邻居节点
通过取余操作首先列表的滚动,模拟一个圈的过程
组合
左右两边相乘表示包含当前位置的组合情况
求解组合Cxn数有两种常见的做法,第一种是1.中的递归解法,都二种是2.中的递推解法
1. :在x个数字中选择出n个数字的组合(python3 for循环中递归,尝试填进当前可能的数字,for循环中递归表示选择当前的数字与不选择当前的数字,当for循环遍历到当前位置的时候表示选择这个元素,当往下递归返回到当前位置尝试下一个位置的时候表示不选择当前的元素,反正到自己就是选择当前元素,下一个的的时候就不选择当前的元素。循环范围为当前递归的位置到列表的长度,往下递归的时候位置是加1的)Cxn
2. :将这些数字分成两个集合进行递推,要当前的数字那么在剩下来的数字中选择n - 1个数字,不要当前的数字那么在剩下来的数字中选择n个数字,这样就可以得到递推组合式子为: Cxn = Cx-1n-1 + Cx-1n,使用两重循环递推得到组合数。
本质上是计算在x个元素中选择n个元素的组合方案
日期
蓝桥杯中关于日期计算的题目:跑步训练/国庆星期日/世纪末星期/星系炸弹/星期一这些题目都需要好好理解做一下,特别是两个日期间隔多少天,多少个星期几,计算某一天为星期几等相关问题的计算,使用python语言那么可以调用相关的api直接进行计算或者是"翻日历"、计算两个日期的以星期为一个周期的方法,此外还可以借助于excel进行计算
数论
主要是关于判断二元方程是否有整数解,逆元的求解,相关的
数学
一个数n的m进制的的位数r为:r = logm(n) + 1
哈希表
找规律
并查集
并查集数据结构可以检查节点之间的连通情况,可以计算出图中连通块的数目,其中并查集有两种写法,一种是初始化father数组元素全为0,另外一种是初始化father数组为本身位置的值,即father[i] = i,两种方法都是类似的,在查找节点与通过father数组来判断连通块的数目的细节有略微的差别,下面蓝桥杯中的七段码是一道经典的使用并查集查计算连通块的数目的题目(使用到了两种不同的写法),可以好好理解一下
全排列
第一种是生成没有重复元素的全排列,生成没有重复元素的全排列一般有两种递归的写法,第一种方法是通过交换列表或者数组中的元素生成对应的排列,这种方法需要初始化列表或者是数组为一开始可选的数字,第二种方法是通过在for循环结合标记列表或者数组递归生成全排列,通过判断当前标记列表对应的数字是否被使用确定是否使用当前的数字。下面算式问题与拼数的题目分别就是对应这两种生成全排列的写法。三羊献瑞/方格填数/寒假作业等都是递归生成全排列之后在递归出口判断是否满足要求的题目(尝试将当前的数字填进到格子中)。第二种是生成具有重复元素的全排列,这个时候需要使用到抓取法生成全排列,下面数列重组是一道生成具有重复元素全排列的经典题目,其实这也是固定的套路了在比赛的时候直接写出对应的代码开干就行。除了抓取法其实还有一种方法是在生成所有的全排列再借助于set集合去重的方法不过这样效率会低一点。其中生成的数字需要填入到二维平面的方格中,并且在二维平面中的数字之间需要满足一定的条件的全排列的题目都是可以使用一维列表的下标在二维平面中填好对应的顺序的方法解决的,这样可以大大降低递归的时间的复杂度,因为在很多情况下很多不满足条件的排列都直接return到上一层而不是递归下去,下面的四阶幻方与方格填数(2015决赛)的题目是使用一维列表下标在二维平面上编号的例子,可以好好理解一下
for循环 + vis标记列表递归生成全排列
也可以调用python中itertools模块中的permutations方法生成全排列
for循环 + vis列表生成全排列
二进制
使用二进制来表示当前的状态(有点像状态压缩),通常会结合位运算,|、&,其中|运算一般是将某一位置为1这样就可以生成一个新的状态,&运算通常是干掉某一个位置的1
二叉树
约瑟夫环
二分查找
二分查找的题目一般都是需要在一个确定的[l, r]范围中找出一个边界使得这个边界满足题目要求的前提下是最佳的,并且这个范围有的时候需要分析题目挖掘出来
栈和队列
在字符串的匹配中,经常会使用到栈衔接与前后匹配元素的作用,利用元素进栈的时候实现字符串或者其他数据类型的前后匹配,所以到遇到类似的问题的时候我们需要想到栈的前后匹配元素的作用,下面小明的作业是一道经典的使用栈对字符串进行前后匹配的问题
动态规划
动态规划可以求解排列组合相关性的问题,下面的垒骰子是一道经典的使用动态思路解决的题目
排列组合的问题可以多往动态规划这方面想想,因为都是可以由前面的状态递推到当前的状态的,将之前状态的组合累加起来那么就可以得到当前状态的方案数目,所以关键是状态之间的转移
数据结构
因为目前使用得最多的是python语言,所以熟练掌握python中常见的数据结构还是挺有用的。一般入门一般语言主要是熟悉常见的数据结构和方法,清楚常见方法的返回值是什么这样有利于进一步处理方法的返回值而且不容易出现语法错误。python中的一个重要而且很方便的一点是允许多个数据类型嵌套在一个数据结构中。python中的元组是不可以修改的,元组中的元素是通过小括号括起来,元组经常被用来封装多个不用修改的属性值,例如二维、三维平面上的某个点,在很多时候它的作用相当于是一个java语言中的一个对象,可以封装多个属性值,作为一个整体可以进行排序等的操作,将元组作为列表中的元素这样通过循环中使用下标访问列表中的元组值。python的列表相当于是动态的数组,可以追加、弹出元素,可以充当栈和队列的作用,多个列表的嵌套还可以表示高纬的数据。字典的两个强大的作用是能够将映射和计数的作用,相当于是一个函数的作用,非常高效的通过访问字典中的键获取对应的值,相当于是java中的HashMap,字典在图论中可以用来创建有向图,collections.defaultdict(list),键表示节点标号,值为与当前标号有联系的节点。集合与字符串与java或者或者是c/c++中的功能是类似的。python中第二个比较重要的点是能够使用正数索引与负数索引进行切片操作,非常方便地截取某一个区间内的元素。
发表评论
最新留言
关于作者
