LintCode 89: k Sum (ナップザック問題)

89 · k 合計
アルゴリズム
ハード

説明
n 個の異なる正の整数、整数 k (k \leq n)(k≤n) および数値ターゲットが与えられます。

合計がターゲットとなる k 個の数値を見つけます。解はいくつあるのか計算してみませんか?


例 1:

入力:

A = [1,2,3,4]
k = 2
ターゲット = 5
出力:

2
説明:

1 + 4 = 2 + 3 = 5
例 2:

入力:

A = [1,2,3,4,5]
k = 3
ターゲット = 6
出力:

1
説明:

方法は1つだけです。1 + 2 + 3 = 6

タグ
に関連する問題

90k
サム II

1689
k サム III

解決策 1: サブセット テンプレートを適用しますが、最終的にはタイムアウトになります。

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) {
    
    
        int pos = 0, solSum = 0, totalNum = 0;
        vector<int> sol;
        helper(a, k, target, pos, sol, solSum, totalNum);
        return totalNum;
    }
private:
    void helper(vector<int> &a, int k, int target, int pos, vector<int>& sol, int sum, int &totalNum) {
    
    
        if (sol.size() > k) return;
        if (sol.size() == k && sum == target) {
    
    
            totalNum++;
            return;
        }        
        for (int i = pos; i < a.size(); i++) {
    
    
            sol.push_back(a[i]);
            helper(a, k, target, i + 1, sol, sum + a[i], totalNum);   
            sol.pop_back();
        }
        return;
    }
};

解決策 2: ナップザック問題に変換する k 制限により、次元が 1 つ増えることに注意してください。

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) {
    
    
        int len = a.size();
        
        //dp[a][b][c]: 前a个数字里面找出b个,其sum为c的方案个数。
        vector<vector<vector<int>>> dp(len + 1, vector<vector<int>>(k + 1, vector<int>(target + 1, 0))); 
       
        for (int i = 0; i <= len; i++) {
    
    
            dp[i][0][0] = 1;
        }
       
        for (int i = 1; i <= len; i++) {
    
    
            for (int j = 1; j <= k && j <= i; j++) {
    
    
                for (int t = 1; t <= target; t++) {
    
    
                    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[len][k][target];
    }
};

ローリング配列最適化空間複雑度を O(k*target) にします:

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) {
    
    
        int len = a.size();
        
        //dp[a][b][c]: 前a个数字里面找出b个,其sum为c的方案个数。
        vector<vector<vector<int>>> dp(2, vector<vector<int>>(k + 1, vector<int>(target + 1, 0))); 
       
        for (int i = 0; i <= len; i++) {
    
    
            dp[i % 2][0][0] = 1;
        }
       
        for (int i = 1; i <= len; i++) {
    
    
            for (int j = 1; j <= k && j <= i; j++) {
    
    
                for (int t = 1; t <= target; t++) {
    
    
                    dp[i % 2][j][t] = dp[(i - 1) % 2][j][t];
                    if (t >= a[i - 1]) dp[i % 2][j][t] += dp[(i - 1) % 2][j - 1][t - a[i - 1]];
                }
            }
        }
        return dp[len % 2][k][target];
    }
};

別のスペース最適化スキーム。

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) {
    
    
        int len = a.size();
        
        //dp[k][t]: 找出k个数字,其sum为t的方案个数。//这a个数字可以是vector a里面的任意k个
        vector<vector<int>> dp(k + 1, vector<int>(target + 1, 0)); 
       
        for (int i = 0; i <= k; i++) {
    
    
            dp[0][0] = 1;
        }
       
        for (int i = 1; i <= len; i++) {
    
    
            for (int j = min(i, k); j >= 1; j--) {
    
    
                for (int t = target; t >= 1; t--) {
    
    
                    dp[j][t] = dp[j][t];
                    if (t >= a[i - 1]) dp[j][t] += dp[j - 1][t - a[i - 1]];
                }
            }
        }
        return dp[k][target];
    }
};

おすすめ

転載: blog.csdn.net/roufoo/article/details/127800191