浅浅记录一下周赛「2022-08-07」

6139. 受限条件下可到达节点的数目

6137. 检查数组是否存在有效划分

6138. 最长理想子序列

受限条件下可到达节点的数目

题目详情可见 受限条件下可到达节点的数目

对于这个题目,直接用vis[]记录访问情况,然后dfs即可

不过注意,这里有一个图的转化问题,需要把edges转换成graph关于图的处理细节,详情可见 图的遍历

检查数组是否存在有效划分

题目详情可见 检查数组是否存在有效划分

对于这个题目,直接用「回溯」的思想,关于回溯的详细介绍可见 回溯(DFS)

每次可以有三种选择:两个相等的元素、三个相等的元素、三个连续递增的元素

显然,如果纯暴力回溯,肯定会超时,所以这里用备忘录emeo[]记录子结果,emeo[i]表示[i..n-1]是否存在有效划分

这个问题的进阶版,可见 经典回溯算法:集合划分问题

最长理想子序列

题目详情可见 最长理想子序列

对于这个题目,其实和「最长递增子序列」如出一辙!关于最长递增子序列的详细介绍可见 动态规划设计:最长递增子序列

先给出第一版代码:

不出意外,超时了!!因为 1s.length105

k = 3,如果当前字母为g,那么它只能接在d e f g h i j为结尾的子序列后面

按照上面代码,我们把区间[0, i-1]全部遍历了,显然有很多无效分支

这里给出一种优化方法:用Map<Character, Integer>记录以某个字母结尾的最长子序列的长度

这里字母最多 26 个,算上绝对值,最多会遍历 52 次,相比于 105 简直少太多了

下面直接给出代码:

进一步优化!!

在上述优化的代码中,用到了一个dp[]来保存以下标为i结尾的最长递增序列的长度;同时还用到了一个Map来保存以某个字母结尾的最长子序列的长度,其实这两者可以合并成一个

让我们来重新定义一波dp[],直接表示以某个字母结尾的最长子序列的长度。由于只有 26 个字母,所以dp的长度为 26 就行!!

下面直接给出代码: