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
Example 1
Input:
List = [1,2,3,4]
k = 2
target = 5
Output: 2
Explanation: 1 + 4 = 2 + 3 = 5
Example 2
Input:
List = [1,2,3,4,5]
k = 3
target = 6
Output: 1
Explanation: There is only one method. 1 + 2 + 3 = 6
思路:dfs可以做;但是会超时;正确姿势应该是dp;
public class Solution {
/**
* @param A: An integer array
* @param k: A positive integer (k <= length(A))
* @param target: An integer
* @return: An integer
*/
public int kSum(int[] A, int k, int target) {
if(A == null || A.length == 0 || target < 0) return 0;
int[] count = new int[1];
Arrays.sort(A);
dfs(A, k, target, count, 0, 0, 0);
return count[0];
}
private void dfs(int[] A, int k, int target, int[] count, int curSum, int step, int start) {
if(curSum > target){
return;
}
if(curSum == target && step == k){
count[0]++;
return;
}
for(int i = start; i < A.length; i++){
curSum += A[i];
dfs(A, k, target, count, curSum, step + 1, i+1);
curSum -=A[i];
}
}
}
思路2:dp, f[i][k][s] 代表,前i个数里面取k个能否使得他们的和是s;
f[i][k][s] = f[i-1] [k] [ s ] + f[i-1] [ k -1 ] [ s - A[i-1]] , 其中k >=1, S-A[i-1] >=0;
public class Solution {
/**
* @param A: An integer array
* @param k: A positive integer (k <= length(A))
* @param target: An integer
* @return: An integer
*/
public int kSum(int[] A, int k, int target) {
if(A == null || A.length == 0 || k < 0 || target < 0) return 0;
int n = A.length;
int t = target;
int[][][] f = new int[n+1][k+1][t+1];
// initial special case;
f[0][0][0] = 1;
for(int i = 0; i <=n; i++){
for(int j = 0; j <=k; j++){
for(int s = 1; s <= t; s++){
if( i == 0 && j == 0){
f[i][j][s] = 0;
}
}
}
}
//calculate matrix;
for(int i = 0; i <=n; i++) {
for(int j = 0; j <=k; j++) {
for(int s = 0; s <= t; s++) {
if(i - 1 >= 0){
f[i][j][s] = f[i-1][j][s];
}
if(i-1 >= 0 && j - 1 >= 0 && s - A[i-1] >=0 ) {
f[i][j][s] += f[i-1][j-1][s - A[i-1]];
}
}
}
}
return f[n][k][t];
}
}
利用滚动数组缩小空间成Space : O(K* Target); 注意滚动数组rolling array的精髓是:循环层数不变,只是申请的f数组产生变化,取模 % 2;还有上面刚开始initial的数组,要放到calculate matrix的循环内进行initial;
public class Solution {
/**
* @param A: An integer array
* @param k: A positive integer (k <= length(A))
* @param target: An integer
* @return: An integer
*/
public int kSum(int[] A, int k, int target) {
if(A == null || A.length == 0 || k < 0 || target < 0) return 0;
int n = A.length;
int t = target;
int[][][] f = new int[2][k+1][t+1];
// initial special case;
f[0][0][0] = 1;
//calculate matrix;
for(int i = 0; i <=n; i++) {
for(int j = 0; j <=k; j++) {
for(int s = 0; s <= t; s++) {
if(i == 0 && j == 0 && s > 1) {
f[i % 2][j][s] = 0;
}
if(i - 1 >= 0){
f[i % 2][j][s] = f[(i-1) % 2][j][s];
}
if(i-1 >= 0 && j - 1 >= 0 && s - A[i-1] >=0 ) {
f[i % 2][j][s] += f[(i-1) % 2][j-1][s - A[i-1]];
}
}
}
}
return f[n % 2][k][t];
}
}