專欄 | 九章算法
網址 | www.jiuzhang.com程序員
題目描述面試
給一個nums[]數組,如[1, 2, 4]
將這些數組合使得: 這些數的和是給出的一個target,如使這些數的和等於4
求這樣的組合有多少個?算法
樣例
[1, 1, 1, 1]
[1, 1, 2]
[1, 2, 1]
[2, 1, 1]
[2, 2]
[4]數組
這些組合均可以,他們的和都是4
因此答案是6微信
算法分析code
1.直觀的想法就是把全部的組合全都找出來,再計算他們的個數就能夠了。那麼,怎麼找全部的組合呢?首先你有一個nums數組,一個target。首先想,能不能把這個問題分解成子問題?能夠。以題目描述爲例,須要[1,2,4]組合成4,能夠分解爲3個子問題:cdn
序列的第一個數爲1,讓[1,2,4]組合成3
序列的第一個數爲2,讓[1,2,4]組合成2
序列的第一個數爲4,讓[1,2,4]組合成0排序
2.上述的想法用DFS就能夠實現,設N爲nums數組的長度,M爲target,可是複雜度達到了O(N^M),這個複雜度過高了。 換一個角度來想想,假設dp[i]爲讓[1,2,4]爲i的組合的數目,若是我dp[1],dp[2],dp[3]都已經求出來了,如何去求dp[4]呢?dp[4]能夠由哪些子問題獲得呢?這個思路和上面的過程是同樣的。面試技巧
序列的第一個數爲1,加dp[3]獲得
序列的第一個數爲2,加dp[2]獲得
序列的第一個數爲4,加dp[0]獲得ip
3.dp[0] = 1
dp[1] = 第一個數爲1,而後加dp[0]獲得 = dp[0] = 1
dp[2] = 第一個數爲1,而後加dp[1] + 第一個數爲2,而後加dp[0] = dp[1] + dp[0] = 2
dp[3] = 第一個數爲1,而後加dp[2] + 第一個數爲2,而後加dp[1] = dp[2] + dp[1] = 3
dp[4] = 第一個數爲1,而後加dp[3] + 第一個數爲2,而後加dp[2] + 第一個數爲3,而後加dp[1] = dp[3] + dp[2] + dp[1] = 6
4.因而dp方程爲dp[i] = dp[i-nums[1]] + dp[i-nums[2]] + ... + dp[i-nums[N]],初始化dp[0] = 1。複雜度O(NM)。
能夠發現,第一種思路和第二種思路其實很相近,他們的區別就是,第二種思路對全部的子過程只計算了一遍,第一種思路可能對一個子過程計算不少遍,例:設dfs(i)能夠求出目標爲i的結果,dfs(4) = dfs(3) + dfs(2) + dfs(0) = dfs(2) + dfs(1) + dfs(2) + dfs(0) 展開到這一步的時候就能夠發現dfs(2)已經被計算了2遍了,而在第二種思路中,每一個子過程只會被計算一遍,那麼,可不可讓第一種想法計算子過程的時候只計算一遍呢?能夠,那就是記憶化搜索。
5.由於題目沒說數據是不是遞增,能夠考慮給數組排序,排序事後 一旦遇到 i - nums[j] < 0的,就能夠直接退出循環。
參考代碼
面試官角度分析
這道題目的是揹包問題當中比較難的面試題目,若是會作01揹包,可以拓展想到這道題目多重揹包怎麼樣處理n個揹包數目,那麼這道題目就可以迎刃而解,可以想出O(n*target)時間複雜度的算法那麼久能夠達到hire
LintCode相關聯繫題
登錄www.lintcode.com, 搜索 backpack便可。
Backpack-i
Backpack-ii
Backpack-iii
Backpack-v
推薦閱讀