google2016面試題-count of smaller numbers after self

shuaishuai3409發表於2016-03-21

這是google2016的面試題,給定一個陣列array[],返回一個計數陣列count,count[i]表示array[]中第i個元素右邊有多少個小於array[i](i>=0)
示例:
輸入:array[]=[3,6,2,1]
輸出:count[]=[2,2,1,0]


分析思路:
不難想到O(n2)的方法,不斷的用for迴圈來找目標值。難點在於如何在小於O(n2)時間複雜度下找到方法。其實像這種統計個數問題我們完全可以採用線段樹的思想來做。先給大家舉個簡單例子:

一維座標軸上我這有三條線段區間,分別為[1,5],[2,5],[4,10],請判斷點2都在哪幾條區間出現過。高時間複雜度的演算法就不寫了,直接上效果非常好的線段樹。

線段樹:和正常的樹類似,只不過每個節點儲存的是一段區間,同時每個節點新增計數變數count,用來記錄哪個數值點在該條線段區間出現過。表示建樹的過程是首先在根節點儲存最大線段區間跨度,然後採用與折半查詢類似的方式建立根節點的左右子樹。以三條線段[1,5],[2,5],[4,10]為例,其線段樹構造如下圖,初始conut為全0.
線段樹

為了判斷點2都在哪些區間出現過,我們需要將三條線段在剛剛建立的線段樹上。線段[1,5]就要切割成[1,3],[4,5],這樣線段樹[1,3],[4,5]這兩個節點的count值要加1,表示[1,5]這條線段出現過,線段[1,5]和節點[2,3]和[4,5]是等價的。同理,線段[2,5]要切割成[2,3]和[4,5],線段樹[2,3]和[4,5]這兩個節點count值也要加1。目前為止節點[4,5]的count計數已經變為了2。同樣線段[4,10]分割為[4,5]和[6.10],對應count值要加1。這樣三條線段就掛在完畢了,只要線上段樹中用折半查詢的方式找到[2,2]這個節點,記錄下經過“掛”的節點的count值,取和就是最終經過的線段數。

明天給啦

相關文章