[乾貨] 線段樹知識點總結

專欄 | 九章算法
網址 | www.jiuzhang.comjavascript

1. 線段樹入門問題

1.1 題目描述

給出數列[1 4 2 3],求給定區間的最大值
例:query(0,1) = 4 query(2,3) = 3 query(0,3) = 4**java

1.2 解題思路分析

一道題可不能夠用線段樹來作,基本是看這道題的操做有沒有區間的性質。也就是在一個區間上的操做是否能夠轉化爲兩個子區間上的操做。
從這題能夠看出:程序員

區間(a,b)的最大值和區間(b,c)的最大值中,取較大的就是區間(a,c)的最大值**複製代碼

很明顯能夠看出這個操做是具備區間的性質。面試

1.3 套路

幾種常見的線段樹的套路算法

1.求區間的和,積,最大值,最match小值,gcd等
2.以當前結點的值做爲結點處理,好比給出N個數,再給一個數,問比這個數大的有多少個(固然,用樹狀數組能夠很好的處理,但有修改時,線段樹就會方便不少)
3.區間加減同一個值,或者區間同時賦一個值(在面試中,一般不會問到,算法競賽中會常常用到)複製代碼

2. 構造

一顆線段樹的構造就是根據區間的性質的來構造的數組

區間劃分大概就是上述的區間劃分。能夠看出每次都將區間的長度一分爲二,數列長度爲n,因此線段樹的高度是log(n),這是不少高效操做的基礎。
上述的區間存儲的只是區間的左右邊界。咱們能夠將區間的最大值加入進來。
微信

區間的第三維就是區間的最大值
加這一維的時候只須要在建完了左右區間以後,根據左右區間的最大值來更新當前區間的最大值便可。
由於每次將區間的長度一分爲二,全部創造的節點個數爲ui

n + 1/2 * n + 1/4 * n + 1/8 * n + ...
=   (1 + 1/2 + 1/4 + 1/8 + ...) * n
=   2n複製代碼

因此構造線段樹的時間複雜度和空間複雜度都爲O(n)spa

2.1 代碼1

線段樹構造代碼模板
3d

3. 區間查詢

構造線段樹的目的就是爲了更快的查詢。

給定一個區間,要求區間中最大的值。
線段樹的區間查詢操做就是將當前區間分解爲較小的子區間,而後由子區間的最大值就能夠快速獲得須要查詢區間的最大值。

query(1,3) = max(query(1,1),query(2,3)) = max(4,3) = 4

上述例子將(1,3)區間分爲了(1,1)和(2,3)兩個區間,由於(1,1)和(2,3)區間的最大值事先已經記錄好了,因此直接拿來用就能夠了。

3.1 層數

每一層最多查詢4個區間

考慮長度爲16的序列構形成的線段樹,區間(0,15)。查詢區間(1,14)。

第一層會查詢 (1,7) (8,15)
 第二層會查詢 (1,3) (4,7) (8,11) (12,14)
 第三層會查詢 (1,1) (2,3) (12,13) (14,14)
 第四層會查詢 (1,1) (14,14)複製代碼

由於是連續的,中間那部分會直接算出來,而後兩邊的兩端繼續往下,仍是4個區間。
由於線段樹的高度爲log(n),因此查詢的時間複雜度爲O(log(n))

3.2 代碼2

線段樹區間查詢模板

3.3 單點更新

線段樹構造代碼模板

如何把這種變化體現到線段樹中去?

例如,將序列中的第4個點更新爲5,要變更3個區間中的值,分別爲[3,3],[2,3],[0,3]

能夠這樣想,改動一個節點,與這個節點對應的葉子節點須要變更。由於葉子節點的值的改變可能影響到父親節點,而後葉子節點的父親節點也可能須要變更。
因此須要從葉子節點一路走到根節點,去更新線段樹上的值。由於線段樹的高度爲log(n),因此更新序列中一個節點的複雜度爲log(n)。

3.4 代碼3

線段樹單點更新模板

若是須要區間的最小值或者區間的和。和構造的時候同理。

4. 相關線段樹面試題 Online Judge

4.1 線段樹構造

Segment Tree Build
Segment Tree BuildII

4.2 線段樹單點更新

Segment Tree Modify

4.3 線段樹區間查詢

Segment Tree Query
Segment Tree QueryII

4.4 線段樹綜合

Interval Minimum Number
Interval Sum
Interval SumII
Count of Smaller Number
Count of Smaller Number Before itself



歡迎關注個人微信公衆號:九章算法(ninechapter)。
精英程序員交流社區,按期發佈面試題、面試技巧、求職信息等

九章算法,IT教育領域的深耕者
相關文章
相關標籤/搜索