須彌之鏡;及相差甚遠分析

謝工在GitChat發表於2013-07-22

今日面試題:一個都不能少

有k個有序的陣列,請找到一個最小的數字範圍。使得這k個有序陣列中,每個陣列都至少有一個數字在該範圍中。

例如:

1: 4, 10, 15, 24, 26
2: 0, 9, 12, 20
3: 5, 18, 22, 30

所得最小範圍為[20,24],其中,20在2中,22在3中,24在1中。

相差甚遠面試題分析

原題

給定一個陣列,我們可以找到兩個不相交的、並且是連續的子陣列A和B,A中的數字和為sum(A), B中的元素和為sum(B)。找到這樣的A和B,滿足sum(A) - sum(B)的絕對值是最大的。 例如:[2, -1 -2, 1, -4, 2, 8]劃分為A=[-1, -2, 1, -4], B=[2, 8], 最大的值為16

分析

如果沒有比較豐富的經驗,這個題目咋一看,有一種不明覺厲的感覺。但只要逐層分析,就可以看到,其實只要分析兩層就可以了。首先我們來看看題目有哪些要點(明確題意,有不清楚的,一定要澄清。):

  1. 子陣列是不相交的

  2. 子陣列是連續的,這個有點多餘,但還是強調一下得好

然後題目的要求是,差的絕對值最大。那我們自然而然能夠想到:找到的兩個不相交的子陣列,一個值要很小,一個值要很大。這樣才能夠保證差的絕對值最大。那如何找到這樣的陣列呢?我們從不相交的這個條件入手。看題目中例子(從簡單的例子出發,發現解決方案,是面試中常用技巧。切記!):

0    1    2    3    4    5    6
2    -1    -2    1    4    2    8

看上面的表格,如果兩個子陣列不想交,我們有六個位置,作為劃分的備選,0和1之間、1和2之間、2和3之間,...,直到5和6之間。這六個位置,都可以將陣列劃分為兩部分。我們設定,陣列長度為n,i將資料劃分為兩部分分別為 [0,i-1]和[i,n-1]。都是兩邊包含的集合。i是從1到n-1的。

對於任意的i,我們得到了兩部分[0, i-1]和[i, n-1]。接下來,就是在這兩部分中,找到一個和最小的子陣列A,以及和最大的子陣列B。那麼A-B的絕對值,就是i這個劃分下,滿足條件的兩個陣列的差的最大值。對於,所有的i而言,這個絕對值最大時的A和B就是我們要找到的。

思路通順了,接下來要確定,找到在i處劃分,和最大以及和最小的子陣列的方法。這裡,就要使用到,我們前幾天分享的動態規劃的思想。那篇文章,大家好好閱讀分析了麼。相信一定能夠給大家帶來很多的啟發。回到這個題目,我們單獨的考慮,給定一個陣列,求和最大的子陣列以及和最小的子陣列。

先分析和最大的子陣列,這個問題,是比較經典的問題了,但是我們這裡要處理的是,求得每一個i左側的最大連續子陣列。作如下分析,假設陣列為X, 假設max_until[i]表示,以i位置結尾的連續子陣列的最大和。max_until[i]和max_until[i-1]是什麼關係呢?

  1. 如果X[i] + max_until[i - 1] > max_until[i - 1] and X[i] + max_until[i- 1] > X[i]。那麼X[i]應該加入到連續子陣列中,max_until[i] = max_until[i-1] + X[i].

  2. 否則max_until[i] = X[i],連續子陣列只有一個元素。

但是,我們要的並不是以i結尾的子陣列,儘管給的例子中是這樣的,我們要的是i之前的所有連續子陣列中,和最大的。並不一定包括i。要如何處理呢?我們再開闢子陣列max_left[i]表示[0,i]中連續子陣列的最大值。那這個值要如何求得呢?我們在遍歷陣列,求得max_until[i]的時候,max_left[i]只需要在max_until[i]和此前儲存的最大值裡取最大的即可。也就是一次遍歷,就可以完全求得max_until陣列和max_left陣列。同理可以求得min_until以及min_left陣列。

這是處理的劃分的左半部分。那麼右半部分呢?

右半部分的思路也是一樣的,只不過,我們在遍歷陣列的時候,需要從右向左進行遍歷。

總結整個方法的流程如下:

  1. 從左向右遍歷陣列,計算max_left和min_left陣列,O(n)時間複雜度

  2. 從右向左遍歷陣列,計算max_right和min_right陣列,O(n)時間複雜度

  3. 然後對於每一個i,i從1開始到n-1,計算max_left[i - 1] - min_right[i], max_right[i] - min_left[i - 1]。選取絕對值最大的。

方法的整體空間複雜度為O(n),時間複雜度也是O(n)。

總結

這個題目,其實是採用動態規劃解決最大連續子陣列和問題的變種,又多了一層思考。面試者在遇到一個新的題目的時候,不要慌亂,對問題進行仔細分析,進而對其進行分解,分解為自己熟悉的問題。那問題也就解決了。

本文來自微信:待字閨中,2013-07-16釋出,原創@陳利人 ,歡迎大家繼續關注微信公眾賬號“待字閨中”。

相關文章