序列生成;及合併總數分析

紫鳳發表於2013-08-12

今日面試題:序列生成

給定一個表示式2^i*2^j,其中i,j為非負整數。請找到一種方法,生成如下序列:

2^0 * 5^0 = 1
2^1 * 5^0 = 2
2^2 * 5^0 = 4
2^0 * 5^1 = 5
2^3 * 5^0 = 8
2^1 * 5^1 = 10
2^4 * 5^0 = 16
2^2 * 5^1 = 20
2^0 * 5^2 = 25
...
...
...

請大家開動腦筋,找到更多的方法。

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

合併總數分析

原題

求正數陣列內和為指定數字的合併總數

比如[5, 5, 10, 2, 3] 合併值為 15 : 有4種 : (5 + 10, 5 + 10, 5 + 5 + 2 + 3, 10 + 2 + 3)

分析

有的時候,一個題目不能夠立刻想到比較優化的想法,就可以先找到一個解決方案,然後根據方案的不足進行優化。而且這個時候,逆轉一下思路,便會柳暗花明。由遞迴到動態規劃,不就是如此麼?

我們設定f(index,sum)表示陣列從index開始到結束組成的sum的總數。那麼,f(index, sum)可以表示為什麼呢? 我們這個題目,就是要最終求得f(0, 15),從頭開始分析,最終組成的和為15的可能組合中,可能包含第0個元素,也可能不包含, 原始陣列為A:

  • 當包含第0個元素時,剩下的表示為f(1, 15-A[0])
  • 不包含第0個元素時,剩下的表示為f(1, 15)

則,f(0, 15) = f(1, 15) + f(1, 15 - A[0])。依次遞迴。遞迴的終止條件是什麼呢?對於f(index,sum):

  • 當和小於等於0的時候,f(index,sum) = 0
  • 當和小於sum的時候, f(index, sum) = f(index + 1, num);
  • 當和等於sum的時候,f(index, sum) = 1 + f(index + 1, sum);

但是,上面的條件,並沒有使用題目中,陣列全是正數,也就是存在負數也可以。如果僅僅是正數,後兩個改為:

  • 當和小於sum的時候, f(index, sum) = 0;
  • 當和等於sum的時候,f(index, sum) = 1;

有一個條件,我們沒有使用,也意味著提升的空間。

可是,上面的方案,時間複雜度是指數級。怎麼做一些改進呢?一般在對一個演算法進行優化的時候,有哪些思路呢?尤其是這種時間很恐怖的?我想很多同學都有這個經驗,就是空間換時間。

大家可以想象動態規劃的思想,大家看如下的狀態轉移方程:

dp[n][m]=dp[n-1][m]+dp[n-1][m-num[n-1]]

dp[n][m]表示前n個元素組成和為m的情況數。初始化dp[0][0]=1,其他為0。寫出狀態轉移方程,大家也就明白了,為何要求全是正數了吧,直白一些,陣列的索引,怎麼可能為負呢?在計算的過程中,將和的情況儲存下來,用空間換時間,整個演算法的時間複雜度為O(n*m),不再是指數級。

【分析完畢】

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

相關文章