Google 面試題 | 132模式 Python 版本

九章演算法發表於2017-08-02

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

題目描述

對n個數的序列,a1,a2,……,an,判斷是否存在i<j<k,使得ai<ak<aj(這樣的[ai,aj,ak]被稱為132模式)。n不超過15000。
樣例1
輸入: [1,2,3,4]
輸出: False
樣例2
輸入: [3,1,4,2]
輸出: True
說明: [1,4,2]是一個132模式
樣例3
輸入: [-1,3,2,0]
輸出: True
說明: [-1,3,2],[-1,3,0],[-1,2,0]均為132模式

解題思路分析

1.一個顯而易見的暴力方法是

列舉i<j<k,再判斷是否有a(i)<a(k)<a(j)成立。這樣做的時間複雜度為O(n^3),對於題目給出的n的大小是無法接受的。

2.用min(j-1)代替a(i)

a. 令min(j)為a(1),a(2),……,a(j)中的最小值,那麼如果[a(i),a(j),a(k)]為一個132模式,則[min(j-1),a(j),a(k)]也必為132模式,反之,如果[min(j-1),a(j),a(k)]不是132模式,那麼對於任意i<j,[a(i),a(j),a(k)]都不會是132模式。

b. min(j)可以用O(n)的時間遞推出來,再列舉j,k,判斷是否有min(j-1)<a(j)<a(k),時間複雜度為O(n^2)。

3.用max(j)代替a(k)

a.與方法2相似,我們也可以省去對k的列舉。令max(j)為a(j+1),a(j+2),……,a(n)中小於a(j)的最大值,那麼a(k)即可用max(j)代替。與方法2中不同的是,此處要求的不是a(j)以後的數中的最大值,而是要小於a(j)的最大值,這個問題當然可以用線段樹或者平衡樹來處理,但過於複雜,其實用棧就可以處理這個問題。

b. 我們從後往前列舉j,如果棧頂元素小於a(j),則將棧頂元素出棧,直到棧為空或棧頂元素不小於a(j),再將a(j)壓入棧。這樣就保證了,棧中元素由棧頂到棧底是非降序的,那麼在a(j)入棧前最後一個出棧的就是棧中小於a(j)的最大值。

c. 有一個小問題是,實際的max(j)可能在列舉到j之前就已經出棧了,而導致實際得到的值並非是a(j)以後小於a(j)的最大值,而只是列舉到j時的棧中小於a(j)的最大值,但這對於原問題的求解來說沒有影響,故仍把該值記為max(j),有興趣的讀者可以自己分析一下。

d. 得到max(j)後,判斷是否有min(j-1)<max(j),如果成立則存在132模式,否則繼續向前列舉j,如果對於所有的j均不成立,則不存在132模式。這樣,時間複雜度為O(n)。

4.Follow up:如何快速統計序列中132模式的組數?

這裡提供一個思路:從後往前列舉i,同時維護一組鍵值對{a(k),ans(k)},ans(k)表示滿足ia(k)的組數,故a(i)對答案的貢獻為所有大於a(i)的a(k)對應的ans(k)之和;加入a(i)後,則將對所有小於a(i)的a(k)對應的ans(k)增加1,同時增加一組鍵值對{a(i),0}。

參考程式

面試官角度分析

這個問題主要考察對問題的分析預處理的能力,三種不同時間複雜度的演算法可以把面試者分成三類,是一道適合面試的好題。給出第二種演算法可以hire,給出第三種可以strong hire。

lintcode相關問題

www.lintcode.com/zh-cn/probl…

九章參考答案

www.jiuzhang.com/solution/13…


推薦閱讀:



歡迎關注我的微信公眾號:九章演算法(ninechapter)。
精英程式設計師交流社群,定期釋出面試題、面試技巧、求職資訊等

九章演算法,IT教育領域的深耕者
九章演算法,IT教育領域的深耕者

相關文章