作者|陳近南
專欄|九章演算法
乙個奇怪的印表機列印時遵守以下兩個特殊的條件:
每次只能列印同乙個字元組成的連續序列。
每次列印可以在任何位置開始,在任何位置結束,列印的字元會將原來已有的字元覆蓋。
給定乙個只包含小寫字母的字串,你的任務是計算用該印表機列印出這個字串所需的最少列印次數。字串長度不超過100。
example 1:
輸入: "aaabbb"
輸出: 2
說明: 先列印"aaa",再列印"bbb"。
example 2:
輸入: "aba"
輸出: 2
說明: 先列印"aaa",再在中間的位置列印"b"覆蓋之前的」a」。
ⅰ.乙個簡單的想法是,給出的字串有幾段不同的字元,就列印幾次,不考慮列印覆蓋的情況。比如aabbc,那就列印三次。這是一種貪心策略,但是在某些情況下不能取得最優解,比如aabba,我們先列印aaaaa,然後列印bb,只需要兩次。
ⅱ.那麼搜尋可行嗎?我們每次搜尋起點在最左邊的列印區間(需要搜尋終點),我們發現通過記錄目前正確列印到了哪個位置,我們可以直接求的下一次列印的起點。因為我們總需要從第乙個出錯的位置開始列印。這樣做是可行的,但是複雜度是指數級別,仍有優化的可能性。
ⅲ.結合之前兩種思路,我們來觀察總結一下,列印出來的字串的特點:
假設某一次印表機列印了若干個'a',像這樣:」aaaaaa」,在這之後列印的字元,無非是三種情況:
● 在這段字串的內部列印,但是不覆蓋這段字串的一端,例如」abbbaa」、」abbada」。
● 在這段字串的外部列印,完全不覆蓋這段字串,例如」bbaaaaaa」、」bbaaaaaaccc」。
● 覆蓋這段字串的一端,例如」baaaaa」、」baaacccccc」。
上面所說的第三種情況,看起來就像後來的字元都列印在」a」組成的字串的外部。事實上,如果列印了一串字串後,再列印一些字元覆蓋這段字串的端點會造成浪費,也就是說被覆蓋的這字串的部分一開始完全沒有必要列印,也不會對最終列印次數造成影響。所以,我們可以假定,列印時不存在浪費,也就是說某次列印可以覆蓋前面某一次列印的(不包含端點的)內部,也可以不覆蓋,但是不能覆蓋前面某一次列印的端點。
ⅳ.對於乙個已知的目標字串s,我們考慮列印出這個字串最左邊的字元s[0]的那次列印,我們總可以在列印方案中,把該次列印放到第一次列印。可以這樣做的理由是,由於c中的假定,其它的列印要麼在這次列印的內部(不包含端點),要麼在這次列印的外部,並且由於包含目標字串的最左端點,所以這次列印也不可能在別的列印的內部。這樣一來我們就可以列舉包含s[0]的那次列印的長度l,然後把原目標字串分為s[0 ~ l-1]和s[l ~ n-1](設原字串長度為n),其中,由a中的假定可知s[0]==s[l-1]必須成立(因為端點不被覆蓋)。s[0 ~ l-1]的最少列印次數實際等於 s[1 ~ l-1]的最少列印次數(也等於s[0 ~ l-2]的最少列印次數),這是因為列印出其中乙個字串的列印方案可以稍加變動變成另乙個的列印方案而不改變列印次數(讀者可以想一想是如何變動的)。s[l ~ n-1]的列印與前面字元的列印沒有關係,可以看成乙個新的目標字串,用同樣的方法分析計算。有兩個特殊情況:l=1時,s[0]==s[l-1]必然成立,這時的答案為1 + s[1 ~ n-1]的最小列印次數;l=n時,應滿足s[0]==s[l-1]==s[n-1],即左右兩端點相等,答案為s[1 ~ n-1]的最小列印次數。
ⅴ.分別計算出s[1 ~ l-1]、s[l ~ n-1]的最小列印次數並相加得到特定l下的列印次數,列舉所有l,對得到的答案取最小值即可得到最終答案。這樣把乙個區間分成兩個小的連續區間求解的方法屬於區間型動態規劃,狀態表示為f[i][j]表示從i到j這段子串最少列印次數。具體可以採用遞推的方式(應先從小到大列舉區間的長度,因為長區間的答案是由短區間的答案確定的)把所有可能的區間的答案都算出來,也可採用記憶化搜尋的遞迴形式實現,邊界條件為:長度為1的區間的字串最少列印次數為1。列舉所有區間的時間複雜度為o(n^2),列舉分段點的時間複雜度為o(n),故總的時間複雜度為o(n^3),額外空間複雜度為o(n^2)。
吹氣球
九章演算法 Google面試題 內積
描述 給定長度為n的a陣列,長度為k的b陣列 你可以從a陣列裡取k個數 規則如下 即每次可以從a陣列的最左邊或者最右邊取走乙個數,取走的數從陣列中移除 將取出的ai按取出的順序組成c陣列 求b與c的內積最大值 b與c內積為 i 0k 1bi ci 解釋1 a 1,4,3,2,5 b 1,2,3,4 ...
九章演算法 Google 面試題 解碼方法
有乙個訊息包含 a z 通過以下規則編碼 a 1 b 2 z 26 現在給你乙個加密過後的訊息,問有幾種解碼的方式 樣例 1 輸入 12 輸出 2 解釋 它可以被解碼為 ab 1 2 或 l 12 樣例 2 輸入 10 輸出 1 演算法 動態規劃 dp 演算法思路 思路 複雜度分析 n表示字串長度 ...
九章演算法 Google面試題 島嶼的個數II
給定 n,m,分別代表乙個二維矩陣的行數和列數,並給定乙個大小為 k 的二元陣列a.初始二維矩陣全0.二元陣列a內的k個元素代表k次操作,設第i個元素為 a i x,a i y 表示把二維矩陣中下標為a i x行a i y列的元素由海洋變為島嶼.問在每次操作之後,二維矩陣中島嶼的數量.你需要返回乙個...