游园安排
吐槽
做这题收获挺多的,如果各位看到我的这句话的话一定得把这道题啃下去。
分析
这道题的原型是最长递增子序列(LIS),如果不明白最长递增子序列的朋友可以点击这里。up主声音很小,但讲的思路还是可以的,记住要学会nlogn的优化算法哈,而不是n^2的算法噢。
当然你不想看也没关系,如果你理解这句话的话…
这是力扣官方的思路,原文链接
如果你想更好的掌握这个模板的话建议来这练练手,上面有原题。
当你看到这里的时候说明你已经掌握了LIS的基本思路。在他nlogn的优化算法中,是采用二分搜索等于或第一个大于它的元素,但如果使用我们自个写的二分的话会超时,毕竟python比较慢,决赛题数据确实是挺大的。
虽然没有提示超时但确确实实已经超过一秒了,放在比赛不给我们过的话就血亏。而python有个标准库bisect能帮助我们优化。
bisect本质上应该还是二分搜索,但如果使用它的话真真切切能够提高速度。
它有两个功能,一个是查找,一个是插入,都是在有序列表中进行的,而且是升序。关于它的具体用法可以跟着小郑一起学习一下,点击这里
ok,学完LIS跟bisect之后就来看下一个问题。
这道题比LIS更棘手的地方就是还要将字母打印出来,我们知道LIS优化的算法里面维护的那个数组里面的元素与结果没有太大的联系,唯一能够联系的地方就是维护数组的长度与最大递增子序列长度对应。而如果要得到它的路径是做不到的。那么这里就需要进行路径还原,进行路径还原的话我们要多开一个与总单词个数一致的数组(记为state),分别记录以每个单词结尾所能达到的最大长度。比如…我们以数字为例,数字大小代码单词的ASCII的大小。起初维护的数组是这样的:1 4 7 9,此时state 存的数据是 1 2 3 4,因为前面四个数是不断递增的,还没有遇到比最后一个元素小的元素。紧接着第5个数5出现了,5比9小,那么就要替换里面的元素,替换谁呢,替换掉7。当替换掉7后,数组变成1 4 5 9,那么在这里以5结尾的最大长度就是3,因此将3加入到state里面。就是如果比最后一个数大就直接增加长度,否则替换掉里面的值,然后长度也截断存入到state数组中,遍历到最后的话就能得出每个元素对应达到的最大长度了。