▎引入
☞『例题』
一道十分easy的题:
☞『分析』
这道题非常的简单,但是如果不会two-pointer的话就很费劲了,我们一定会首先想到动态规划,或者直接上暴力,时间复杂度绝对不能在这么大的数据规模下接受。
那么two-pointer是什么?
正如其名,有两个指针,注意:此指针非彼指针,可不是C++中的指针,所以不必担心,并不难,非常easy。
两个指针分别是头指针l和尾指针r,这样这道题的算法就很清晰了:当区间[l,r]中的数都出现过一次时,那么就头指针l++,同时更新答案,否则尾指针r++。
总的算法时间复杂度是O(n),也是相当快了。
▎two-pointer(尺取法)
☞『定义』
two-pointer英文直译过来叫做双指针法,意译过来叫尺取法,(小编不了解为什么叫尺取法,觉得叫two-pointer就挺舒服的,所以下文会一直叫英文名称)。
尺取法是一种比较基础的算法,一般用来解决具有单调性的区间问题. 不过,一般满足单调性的问题二分也可以做到,所以往往two-pointer能解决的题二分也可以做到。
☞『two-pointer的用处』
two-pointer通常只起到辅助或优化的作用。
其实我们或多或少已经接触过two-pointer了,只不过你不知道它叫什么名字,所以这篇博客中的two-pointer部分只是莫队的垫脚石。
▎莫队
☞『引入』
莫队几乎就是two-pointer,只是处理的问题不太一样。废话不多说,直接先上一道题:
洛谷P1494
一般莫队就是处理这样的查询多次区间的问题。(有兴趣可以做一做)
☞『定义』
莫队算法主要是用于解决不带修改只有查询的一类区间问题。
☞『算法思想核心』
比方说当前有一个大区间(也就是数列),还有若干查询的区间。
假设我们已经知道一个区间[l,r]的答案是多少。
那么我们就可以轻易扩展:
我们就可以用极少的时间O(x)知道[l,r+1],[l,r-1],[l-1,r],[l+1,r]的答案,以此来暴力扩展至下一个询问区间,就能知道它的答案了。
所以这是极其暴力的。
☞『为什么说它是优雅的暴力』
这个算法时间复杂度是O(n√nx),最坏也不会到达O(n),因此,尽管暴力,也很优雅。