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];
}
};