算法补天系列之中级提高班1

本文探讨了滑动窗口技巧在优化问题中的应用,如绳子覆盖问题和硬币找零的高效解法。通过贪心策略和滑动窗口算法降低时间复杂度,并展示了如何通过预处理和打表法简化问题。讨论了动态规划在找零问题中的优化,以及如何利用二进制编码解决特定问题。
摘要由CSDN通过智能技术生成

今天的主要技巧

滑动窗口,很多O(N)的思路就是这么来得
打表,简单格式的输入输出。
预处理数组/结构,省重复连续遍历。

题目一:

在这里插入图片描述

初始思路:假设绳子右侧点正好压住了这个点,然后看左边压了多少个点,这个是一个小的贪心策略
那我们要怎么实现这个思路:遍历吗?找一个>=绳子左距离的最短的点,可以用二分,找到之后就可以直接计算出来右边压在这个点能覆盖的点的数量

这个思路的时间复杂度N*logn

换个思路:有没有更好的方法,有。就是类似滑动窗口的思路。叫绳子的左边来压到每一个点。然后叫右边的串口去动,可以直接照着点去移动,然后确定绳子长度不超标就行,这里的实现方式可以理解为双指针(毕竟这两个确实是一个东西),这样的优势在于不会回退

所以时间复杂度:O(N)

来看看题目2:

在这里插入图片描述

看起来想找硬币那道题,可以用dp来做,不过也有不同,这道题我们最后可以优化的更好。
(ps:其实这道题>24个的偶数都能有结果)
我们思路1:暴力尝试,我们先看8个的袋子,最多要用多少个,然后每一次减一个,看6个的袋子能不能装剩下的,如果能正好装好,就直接OK,返回结果。一路见到8个的袋子没有了,要是还没有结果就返回-1。

这个思路可以优化吗?可以,我们不用试所有的8个袋子个数的类型。实际上,当我们一个个的减少八个苹果袋子的数量,导致留给六个的袋子的苹果数量>24个的时候,就没有必要去试了。因为这个时候我们会发现循环。因为将超过的部分分给八个的袋子之后,剩下的交给六个的袋子的苹果数你一定之前遇到过。

为什么,因为这样想,如果超过了24个,你用六个的袋子就算出结果了,你觉得能对吗?如果有结果,你一定可以用八个的先装好!!!
在这里插入图片描述

这个看起来很复杂,但是实际上是O(1)的方法,因为我们循环不了几次就出结果了。

这个思路很nb了对吧,但是这个思路本身是具有很强的局限性的。换个题目就不好使了。

但是这个时候我们说,当我发现一个题目,入参是整数,出参也是整数,我们可以一开始用一个很蠢很粗暴直接的方法,然后发现了规律之后,再去进行优化。
这个就是之前这个思路的代码的结果,发现规律了吗?
在这里插入图片描述

这个就是打表法,原理?思路?逻辑?爱谁谁,我就问这个规律做出来对不对吧?(ps:对)
甚至我还可以大胆的说,这个绝对绝对是最优解。还能有比这个更简单更快的吗?
另外补充一句,网上那些搞数学规律解题法的基本都是,先自己打表打出来结果,再去想数学的解释方式,最后写出一个基本看不懂的帖子来装逼。这种人下次见了就别惯着。

不是所有int->int的题目能这样,但是这样的题目确实是不罕见。约莫能有四成。

我们再来一个题目:

先后手两个动物来吃草,他们只能吃4^n的草并且不能不吃,我们现在有n份草,谁先吃完谁就赢了。问谁能赢?

好了,请问粗暴的代码怎么写?
前面几份草很简单,我们自己分析一下就行了。我们可以简单分析一下前面0-4的情况。

往下怎么做?

我们就问当前我吃1,4,16…份,问能不能找到一条路让我赢。找到了,就赢了。所以我们可以直接递归求,记得这个时候我们先后手转换了,每一次当前吃的4,看剩下的草自己转后手有没有机会。
在递归的时候注意一下,小心
4之后溢出了。如果32位成了1,成了负数就是会无限循环了。所以我们要和N/4比较。
没有,那就是对面赢了
好了,我们把草从0-50份,用这个思路出一下结果。这个明显吗?
在这里插入图片描述

对吧,后先后先先的一个规律。
只要输入输出格式简单一些。我们就可以这样来看一下思路。
我甚至可以想到网上那些帖子的嘴脸了,一个个都是大数学家。给你一通分析,真的是。。。

我们再来看一个题目:

在这里插入图片描述
补充说明一下,这里的这个左侧是一个虚指,你可以叫左边两个是左侧,也可以叫整个是左侧,也可以整个都是右侧,左侧为空。
所以,我们可以枚举左侧部分的大小情况。统计一下有多少个G,染成R就可以了
这个是一个O(N^2)的方法,我们需要遍历两轮嵌套。但是里面的东西是一样的,我们来回来去遍历,实在是浪费。
那么我们能不能改善一下呢?我们可以设置一个数组,统计0-i范围上,R的数量,再做一个数组,统计i-N-1上,G的数量,有了这个,我们就不用每一轮都遍历一遍整个的了。直接取数组的数据就可以了。

这个就是数据的预处理。用空间换时间,把一些经常要遍历的数据我们通过存储遍历结果,省去后续还需要的空间。

再来一个例题:
在这里插入图片描述

首先,我们要知道n*n规模的矩阵,里面的子矩阵的数量是n4的规模。正方形子矩阵的数量是n3的规模。

那么这道题我们要怎么下手呢?
我们首先来一个粗暴的,那就是遍历行和列,二重循环确定左上角的点,然后遍历这个正方形的边长,注意边长的遍历上限。
好了,我们现在已经三重循环了,我们还要验证这个正方形的四条边,是不是数值都为1.
那么我们现在就是嵌套三个循环之后优嵌套了一个穿行的四个循环。太逆天了。
所以,我们要把验证数据的时间省下来。

这么看我们肯定是需要预处理的吧,这个应该没有什么疑问了,我们首先需要做一个矩阵,统计这个节点往右看,有多少个连续的1,再做一个矩阵,统计这个节点往下看,有多少个连续的1。
这个矩阵怎么用就很好联想了吧。
就是我们根据边长,去取矩阵的数据,和边长去比,大于边长就可以了。
这样一来,我们就从O(N4)->O(N3)

最后再来一个题目

在这里插入图片描述

这种题目也不罕见,一般这种问题,统一一个思路,那就是用二进制来拼。

我们来想一下,1-5的函数,可不可以改成等概率的0-1随机?

可以,只要1,2,我就返回0,随机到3,4,我就返回1,随机到5,我就叫他再随机一次

懂了吗?只要我们能0-1等价,我们就可以通过二进制返回所有的数据,多出来的就叫他再去随机一次,重新做就行。

所以第二问就好办了,首先改0-1等概率发生器。然后看要求的范围改成0-n之后,看要几个二进制位。然后对应的0-1去随,然后超了重新来就行了。

至于最后一个,那就需要点技术了,我们叫它随机两次,00,11都不要,01,10我们叫它分别对应0,1,这两个的概率都是p(1-p),刚好等概率,打完收工。

下一道题(没想到吧)

在这里插入图片描述

就是递归的思路,左树的情况*右树的情况

再来一道题(这回真的最后一个了)

在这里插入图片描述

首先,我们要会判断这个括号字符串完整不完整。这个好办,就一个变量统计左括号-右括号,遍历一遍字符串就行,如果变量不曾<0且最最后变量等于0.
那么这个怎么办也简单,就是遍历一遍,如果变量要<0了,就加一个括号,最后变量>0了,加变量个括号即可

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值