Google賽馬;及最大矩形分析

紫鳳發表於2013-08-06

今日面試題:Google賽馬

想必田忌賽馬的故事,大家都耳熟能詳。但是,大家知道Goolge的童鞋們是怎麼賽馬的麼?不過,首先,大家要先嚐試一下:有25匹馬,每次只能五匹一起跑,那麼最少跑幾次,才能確定前三甲呢?

=====================================================

最大矩形分析

原題

在一個點陣圖中找面積最大的白色矩形:給你一個NxN的黑白點陣圖,找一個面積最大的全白色的矩形。注意了,是一個矩形,不是任意一個白色相連的區域。你的演算法能夠達到的最好的時間複雜度是多少呢?

分析

為了方便進行分析,我們假設黑色位置都是0,白色的位置都是1.題目的問題就轉化為,找到一個最大的矩形,其中所有的元素都是1.

遇到這樣的題目,該如何分析呢?這是一個矩形,是二維,是否是由一維的某些問題擴充套件而來的呢?一維的問題的解法,是否可以擴充套件到二維呢?我們看下面的題目:

在柱狀圖中找最大的矩形:給一組非負的整數來表示一個柱狀圖,設計一個演算法找到最大面積的能適合到柱狀圖內的矩形。比如,對與這組數,1 2 3 4 1 ,有兩種可能的方案,一種是適合到 2 3 4 內的矩形,面積是 2*3;另一種是適合到 3 4 內的矩形,面積是 3*2。你覺得能有O(n)演算法嗎?

上面的題目,我們在微博上都討論過的。大家還記得,一維的時候,是怎麼樣的解法麼?思路如下:

一個線性演算法是用堆疊來儲存當前可能的矩形(高度和起始位置)。從左到右掃描,對一個元素,如果 a)大於棧頂元素, push; b)小於的話,pop所有的大於它的元素,計算面積,更新最大值。這時如果堆疊空,push一個新的元素,高度等於當前元素,起始位置為0;否則,push當前元素高度和棧頂的起始位置。

這是一個很巧妙的解法,是否能夠應用到二維的情況呢?在微博中,我們簡短的給出了一個思路。下面,我們在這裡詳細討論,針對如下例子,有矩陣A:

1 1 0 0 1 0
0 1 1 1 1 1
1 1 1 1 1 0
0 0 1 1 0 0

上面的這個矩陣,該如何轉化為一維的情況處理呢?最直接的思路如下:

第一行作為一維的情況處理;

第一行、第二行,對應列相加,生成一個新的陣列,然後應用一維的處理情況;

第一行、第二行、第三行,對應列相加,生成一個新的陣列,然後應用一維的處理情況;

...直到整個矩陣都包括在內;

第二行作為一維的情況處理;

第二行、第三行,對應列相加,生成一個新的陣列,然後應用一維的處理情況;

...一次類推

上面的思路是可行的,但是時間複雜度是n^3的。如何進一步改進呢?思路也是從上面的過程中得到的。

生成新的矩陣C,C[i][j]表示第j列,從第i個元素開始,包括第i個元素,向上數,直到遇到0時,1的個數。則C為:

1 1 0 0 1 0
0 2 1 1 2 1
1 3 2 2 3 0
0 0 3 3 0 0

上面這個矩陣的構造,遍歷一邊A的全部元素即可。n^2的時間複雜度。這個矩陣的最大作用,就是將上面思路中,跨幾行考慮的情況,都變為一行了。時間複雜度降了一個級別,每一行,應用一維處理處理的情況,就可以得到最終的結果。

將上面斜體的描述轉換為如下步驟:(h, i),h表示C[i][j]的大小,可以理解為矩形的高度,i表示起始位置,第三行為例:

i C[i] 棧操作 最大值 棧內容
0 1 push (1,0) (1,0)
1 3 push (3,1) (3,1)(1,0)
2 2 pop (3,1),push (2,1) (2-1)*3=3 (2,1)(1,0)
3 2 什麼都不做 (2,1)(1,0)
4 3 push(3,4) (3,4)(2,1)(1,0)
5 0 pop(3,4) (5-4)*3=3 (2,1)(1,0)
5 0 pop(2,1) (5-1)*2=8 (1,0)
5 0 pop(1,0) (5-0)*1=5

則得到這一行的最大值為8。

總結演算法過程如下:

初始(h,0),入棧;

遍歷後續元素:

  • 如果h > h_top, 則入棧;

  • 如果h = h_top, 則不進行任何操作;

  • 如果h < h_top, 出棧,直到棧頂元素的高度小於h,每次出棧,更新最大值(i - i_pop)*h_pop > max ? (i - i_pop)*h_pop : max;此時如果h>h_top,則push (h, i_lastpop),如果棧為空,則push (h, 0).

直到元素遍歷完畢

【分析完畢】

本文來自微信:待字閨中,2013-08-01釋出,原創@陳利人 ,歡迎大家繼續關注微信公眾賬號“待字閨中”。 【分析完畢】

相關文章