关于算法优化的思路启发

拿到一个算法题无从下手?怎么办?

我们总是会习惯于责怪自己的知识不足,掌握的数据结构和各种算法不够多,然而,刷题并不是需要等你学完所有的知识才回头进行的过程。

我们需要明确的几件事:

1.暴力、模拟、枚举最简单有效却最慢

2.上述方法慢的原因是多了很多不必要过程,这些过程经过优化就是所谓的高级算法

举个很简单的例子:

现给出n个数,需求是给出i,要你求1~i位置上的最大值,设查询次数为m。

暴力法:每次询问遍历一遍记录最大值,O(m*len)。

优化思路:假设我们现在有1~i位置的最大值,那么在求1~i+1的查询结果时,只需要max(result(1,i),A[i+1])就可以得到结果。

那么如果查询的i不是依次间隔为1上升呢?

如果题目不是要求强制在线,那我们为什么不能将所有的查询升序排序,现假设第i次的查询为m(i),那么由mi推到m(i+1),只需要遍历得到m(i)+1~m(i+1)上的最大值,和mi的查询结果取max即可,这就是莫队算法(优雅暴力),复杂度就是遍历一遍整个数组O(n)。

如果题目要求结果按照输入的顺序输出结果,你是不是要叹气没法优化了呢?

哎呀呀,它又不是让你一定要查询一次输出一次,那么你只要把查询和它的输入顺序绑定,将查询排序后,按照上述的优化求解,最后把结果放到某个数组中和该查询绑定的输入顺序的索引上,不就可以了吗。

如果再变态一点,要求你一次查询一次输出怎么办呢?

等一下,别总是叹气呀,谁说没有办法了。刚刚我们的优化全是在查询上做的,现在人家只是不让你在查询上动手脚,那可以找别的方法嘛!

你想想,他的mi的取值范围是[1,n],所以你只要把这n种情况处理一下,最后查询的时候直接从所有的解里面拿出需要的不就好了,n种情况处理的复杂度就是遍历一遍数组,复杂度是O(n)。

那么更高级一点的优化呢?那就和数据结构扯上关系了。我们知道没有一种数据结构可以解决所有的问题【你发明了,下一届图灵奖就是你的】。各种数据结构都有它擅长解决的问题,也有它自身的缺陷。

优化和数据结构有什么关系呢?当然有咯。

举个栗子叭,现在有n个空队列,现在有如下几种操作:1.翻转队列  2.将某个队列接到另一个队列的后面  3.从队列头取值(空队列输出-1)

先从暴力模拟看起:暴力模拟它的行为,开n个队列,按照相应的操作进行维护。可以手动实现队列,也可以用语言自带的,不过终究是常数级的优化罢了,不改暴力之面目。

说好的优化呢?我们看一下这几个操作,取值O(1),无法优化,翻转O(len),有点费时哦,想想办法,重接链表O(len),看来优化的重点自然是后面两个了。

首先呢,对于翻转,我们不要学乖,让你翻转你偏不翻转,找一些别的方法,比如,打个标记reverse,如果标记为真,表示已经翻转,那么这个时候找头即是找尾,复杂度瞬间变成O(1)了耶!

再来:重接队列。emmm,没有办法嘛?nonono,一样可以打个标记over嘛,如果队尾的over为真,表示这个尾巴不是真的尾巴,而这个值,可以表示真的尾巴所在的队列的索引,然后去那个队列里面找。等一下!这样的话,接过来的那个队列不就不能用了嘛???题目让你开n个你就开n个嘛,就不会多开点,然后建立一张索引表,建立起 队列号->真索引 的映射,又解决了不是,O(1)。嗯,乍看没问题,可是,如果重链接操作过多,数组有可能不够用呢,怎么办呢?

我们绝对不能去复制,这样就成了O(len)的算法,怎么办,有没有适合重接的数据结构呢?链表哇!!!这次可是基于数据结构的优化呢!!!再细细抠一下,因为存在先翻转后重接的情况,所以需要建成双向链表。题解完毕。

怎么样,虽然没有说到一些数学上的优化,但是这些优化对付一般的题目完全足够了哦。

猜你喜欢

转载自blog.csdn.net/qq_39304630/article/details/81709579