K Sum

Given n distinct positive integers, integer k (k <= n) and a number target.面試

Find k numbers where sum is target. Calculate how many solutions there are?數組

Example

Given [1,2,3,4], k = 2, target = 5.There are 2 solutions: [1,4] and [2,3].Return 2.優化

這是sum一系列問題中的終極版本,即求給出的n個數字中,取其中k個數字,最終和爲target的組合有多少。spa

注意這題問的是有多少,並非要求給出全部的符合條件的k個數組的所有組合。按照前面的2 sum, 3sum, 4sum等題推理若是採用排序加雙指針夾逼的方法,複雜度是O(n^(k-1))的,若是採用4sum這種利用2sum hashmap的作法,則最優的複雜度爲有下降,可是4sum這種已經很複雜,對於更大的k爲偶數的狀況,會變得特別複雜。以上分析能夠看出DP是這時候的好選擇。指針

首先看這題自己的描述,n個取k個,組成和爲target的狀況,其實看描述很是像揹包問題,容量是這裏的target,可是揹包問題自己不要求知道一共是多少個物體組成,且不須要知道方案數,因此二維的DP沒法解決。咱們能夠定義3維的DP狀態:f[i][j][t]即前i個字母中取出j個能組成和爲t的狀況的種數。code

定義轉換狀態:f[i][j][t] = f[i-1][j][t] + f[i-1][j-1][t-nums[i-1]]和揹包問題同樣,咱們須要對取不取第i 個數字作一個判斷。blog

初始化,這個是最tricky的地方,究竟如何初始化纔對。首先數組中的全部的數字都是正數,且都不相同。因此f[i][1][A[i-1]]應該都是1. f[i][1][A[j]] = f[i-1][1][A[i]]+f[i-1][0][0], f[i-1][1][A[i]]確定是0,因此f[i-1][0][0]的值是1.能夠先進行初始化。排序

最後的結果是f[n][k][target].複雜度爲O(k*n*target).上述空間複雜度能夠採用滾動數組優化爲二維的(在n這一維度進行優化)。get

代碼以下:hash

class Solution:
    """
    @param A: An integer array.
    @param k: a positive integer (k <= length(A))
    @param target: integer
    @return an integer
    """
    def kSum(self, A, k, target):
        n = len(A)
        dp = [[[0] * (target+1) for i in xrange(k+1)] for j in xrange(n+1)]
        for i in xrange(0, n+1):
            dp[i][0][0] = 1
        for i in xrange(1, n+1):
            for j in xrange(1, min(k+1,i+1)): #j的範圍必定要注意 for t in xrange(1, target+1):
                    if t < A[i-1]:
                        dp[i][j][t] = dp[i-1][j][t]
                    else:
                        dp[i][j][t] = dp[i-1][j][t] + dp[i-1][j-1][t-A[i-1]]
        
        
        return dp[n][k][target]

這題三維的滾動數組優化比較困難,嘗試了幾回都有問題。後序再說。

這題難度比較高,面試中出現的機率比較低,但仍然是一道不錯的DP題。

相關文章
相關標籤/搜索