求正數陣列內和為指定數字的合併總數
比如[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:
則,f(0, 15) = f(1, 15) + f(1, 15 - a[0])。依次遞迴。遞迴的終止條件是什麼呢?對於f(index,sum):
但是,上面的條件,並沒有使用題目中,陣列全是正數,也就是存在負數也可以。如果僅僅是正數,後兩個改為:
有乙個條件,我們沒有使用,也意味著提公升的空間。
可是,上面的方案,時間複雜度是指數級。怎麼做一些改進呢?一般在對乙個演算法進行優化的時候,有哪些思路呢?尤其是這種時間很恐怖的?我想很多同學都有這個經驗,就是空間換時間。
大家可以想象動態規劃的思想,大家看如下的狀態轉移方程:
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),不再是指數級。
具體**如下:
int totalcountrecusive(vector& data,int index,int sum)
int totalcountrecusive(vector& data,int sum)//遞迴方法
int totalcountdp(vector& data,int sum)//動態規劃方法
for(i = 0;i <= length;i++)dp[i][0] = 1;//初始化
for(i = length-1;i >= 0;i--) }
return dp[0][sum];
}
待字閨中之單鏈表和之戀
題目 原題 兩個單鏈表 singly linked list 每乙個節點裡面乙個0 9的數字,輸入就相當於兩個大數了。然後返回這兩個數的和 乙個新list 這兩個輸入的list長度相等。要求是 不用遞迴 要求演算法在最好的情況下,只遍歷兩個list一次 最差的情況下兩遍 分析 如果鍊錶表示的數是從低...
LEETCODE 和為s的連續正數數列
輸入乙個正整數 target 輸出所有和為 target 的連續正整數序列 至少含有兩個數 序列內的數字由小到大排列,不同序列按照首個數字從小到大排列。示例 1 輸入 target 9 輸出 2,3,4 4,5 示例 2 輸入 target 15 輸出 1,2,3,4,5 4,5,6 7,8 最容易...
正數陣列的最小不可組成和
給定乙個正整數陣列arr,其中所有的值都為整數,以下是最小不接組成和的概念 arr 1,2,3,4 返回11 arr 2,3,4 返回7 public intbaoli intarr for int i min 1 i integer.max value i return0 public void ...