1. 程式人生 > >89 k數和

89 k數和

length 代碼 color aps 實的 數據 方程 ref rip

原題網址:https://www.lintcode.com/problem/k-sum/description

描述

給定n個不同的正整數,整數k(k < = n)以及一個目標數字。 

在這n個數裏面找出K個數,使得這K個數的和等於目標數字,求問有多少種方案?

您在真實的面試中是否遇到過這個題?

樣例

給出[1,2,3,4],k=2, target=5[1,4] and [2,3]2個符合要求的方案

標簽

LintCode 版權所有 動態規劃(DP) 思路:最開始參照了k數和Ⅱ用遞歸來做,結果只通過18%的數據就Time Limit Exceeded了。點開標簽一看,要用動態規劃……一口老血。
好吧,動態規劃就動態規劃。剛做過背包問題,背包問題中用背包容量作為動態數組一個維度,另一個維度是取0~i個物體,dp值是當前最大容量。而這道題,目標數字相當於背包容量,要作為一個維度,但與背包問題不同的是,這道題是從前i個中取出若幹個,又多出一個維度,所以要用三維動態數組,dp值表示當前方案數,大爺的…… dp【i】【j】【t】表示從前i個數中取出j個,這些數的和要等於t,有多少種方案。 狀態轉移方程:dp【i】【j】【k】=dp【i-1】【j】【t】+dp【i-1】【j-1】【t-A【i】】(當然前提是t>=A【i】);
                    dp[i][j][t]=dp[i-1
][j][t]; if (t>=A[i])//註意是大於等於; { dp[i][j][t]+=dp[i-1][j-1][t-A[i]]; }

意思就是,每個元素都有兩種狀態,取或者不取:

(1)若不取A[i]這個值,當前方案數等於從前i-1個數中取j個使其和為t的方案數,即dp[i - 1][j][t]。

(2)若取當前值A[i],則當前方案數等於從前i-1個數中取j個使其和為t的方案數再加上考慮A[i]的情況,即dp[i - 1][j - 1][t - A[i]](前提是t - A[i]要大於等於0)。

值得註意的是,如果j為0並且t也為0,則dp【i】【j】【t】=1,即是說從任意集合裏拿出0個數使其和為0,這種情況只有一種方案,就是不取任何數。 AC代碼:(註意代碼實現的時候對i做了處理,因為第一個數下標是0,或者也可以單獨處理i=0的情況)
class Solution {
public:
    /**
     * @param A: An integer array
     * @param k: A positive integer (k <= length(A))
     * @param target: An integer
     * @return: An integer
     */
    int kSum(vector<int> &A, int k, int target) {
        // write your code here
    int size=A.size();
    if (target<0)
    {
        return 0;
    }
    vector<vector<vector<int>>> dp(size+1,vector<vector<int>>(k+1,vector<int>(target+1,0)));
    

    for (int i=0;i<=size;i++)
    {
        for (int j=0;j<=k;j++)
        {
            for (int t=0;t<=target;t++)
            {
                if (j==0&&t==0)//前i個數中取0個和為0只有一種方案,就是不取任何數;
                {
                    dp[i][j][t]=1;
                }
                else if (!(i==0||j==0||t==0))
                {
                    dp[i][j][t]=dp[i-1][j][t];
                    if (t>=A[i-1])//註意是大於等於;
                    {
                        dp[i][j][t]+=dp[i-1][j-1][t-A[i-1]];
                    }
                }
            }
        }
    }
    return dp[size][k][target];
    
    }
};

空間優化: 一道題做了好久……各種細節出錯,不參照答案寫不出來,多維動態數組對我而言還是有一定難度的,哭…… 參考: lintcode: k Sum 解題報告 LintCode-k數和 LintCode -- k數和 標記下我最開始的遞歸代碼:
class Solution {
public:
    /**
     * @param A: An integer array
     * @param k: A positive integer (k <= length(A))
     * @param target: An integer
     * @return: An integer
     */
    int kSum(vector<int> &A, int k, int target) {
        // write your code here
    int result=0;
    if (A.empty())
    {
        return result;
    }
    ksum(A,k,target,0,0,0,result);
    return result;
    }
    
    void ksum(vector<int> &A, int k, int target,int sum,int ind,int size,int &result)
{
    if (size==k)
    {
        if (sum==target)
        {
            result++;
        }
        return ;
    }
    if (ind>=A.size())
    {
        return ;
    }
    ksum(A,k,target,sum+A[ind],ind+1,size+1,result);
    ksum(A,k,target,sum,ind+1,size,result);
}
    
};

89 k數和