大家好,欢迎阅读算法数据结构专题,今天我们来聊聊一个新的数据结构,叫做线段树。
线段树这个数据结构很多人可能会有点蒙,觉得没有听说过,但是它非常非常有名,尤其是在竞赛圈,可以说是竞赛圈的必备技能。所以如果以后遇到有人看了一点算法导论就在你面前装逼,你就可以问他:请问线段树更新的复杂度是多少?
不过如果你会线段树,你也要小心一点,最好不要在面试的时候随便透露你会这个算法。否则面试官一下子就会知道你是圈里人,然后你会发现你后面的面试问题比之前好像难不少。当然也有可能遇到面试官自己不会,为了防止尴尬强行让你用非线段树的解法来完成,比如我就遇到过……
例题
说了这么多废话,那么线段树究竟是什么呢?线段树的英文是segment tree,其实也算是一个直译。因为这个数据结构和线段没有特别大的关系,我个人感觉翻译成区间树可能更贴近一点。
我们先理解到这里,就是这个数据结构大概和区间有点关系。我们先放一放,先来看一道例题,来实际体会一下,为什么需要线段树这个数据结构,以及它的使用场景究竟是什么。这样我们可以对它有一个更加直观的感受,这道题很简单也很经典,我就是在这道题遇到了面试官不让用线段树的突然袭击。
这道题的题面是这样,给定一个长度为n的数组。这个数组当中有n个整数,然后我们会有两种操作。一种操作叫更新,我们指定更新某一个位置的某个数,第二个操作叫query,给定一个区间,要求这个区间里面元素的最小值。n的范围呢是 1 0 5 10^5 105,操作的数量也是 1 0 5 10^5 105,请问我们应该怎么实现?
线段树概念
当然你可能已经知道要用线段树了,只是不知道线段树是什么以及怎么使用。我们先把这些疑惑放在一边,就单纯简单地用最朴素的方法来思考的话,我们会发现我们每次查询都是 O ( n ) O(n) O(n)的操作。最坏的情况下,我们就是要求整个数组的最小值,那么我们需要依次遍历整个区间来求。那么复杂度再乘上操作的数量,整个程序的复杂度会达到 1 0 10 10^{10} 1010。显然这是一个非常巨大的数字,在算法竞赛场景当中一定会超时。
也就是说简单粗暴是做不出来的,如果你有足够多的做题经验,你就会很自然地想到我们也许需要使用一些数据结构来优化这个查询的复杂度。