题目:组合总和Ⅲ
描述:
找出所有相加之和为 n
的 k
个数的组合,且满足下列条件:
- 只使用数字1到9
- 每个数字 最多使用一次
返回 所有可能的有效组合的列表 。该列表不能包含相同的组合两次,组合可以以任何顺序返回。
示例 1:
输入: k = 3, n = 7 输出: [[1,2,4]] 解释: 1 + 2 + 4 = 7 没有其他符合的组合了。
示例 2:
输入: k = 3, n = 9 输出: [[1,2,6], [1,3,5], [2,3,4]] 解释: 1 + 2 + 6 = 9 1 + 3 + 5 = 9 2 + 3 + 4 = 9 没有其他符合的组合了。
示例 3:
输入: k = 4, n = 1 输出: [] 解释: 不存在有效的组合。 在[1,9]范围内使用4个不同的数字,我们可以得到的最小和是1+2+3+4 = 10,因为10 > 1,没有有效的组合。
关键词:回溯
说明:
这道题跟昨天的题十分相似,我这里就不过多赘述了。
但这道题的dfs结束条件很有意思。这道题我们设定void dfs(int num,int k, int n, int*tmp),其中num是1-9的某一个数,n,k表示我还差k个数构成和为n的序列。
很显然的一个终止条件就是n==0&&k==0。
另外几个终止条件分别是:k==0&&n>0;k>0&&n==0;num>9;k<0||n<0。
因此我们有如下代码:
void dfs(int num,int k, int n, int*tmp){
if(k==0&&n==0){
int*tmpAns = (int*)malloc(sizeof(int)*1001);
for(int i = 0 ; i < tmpSize ; i++){
tmpAns[i] = tmp[i];
}
ans[ansSize] = tmpAns;
Colunm_ans[ansSize++] = tmpSize;
return;
}
if(num>9) return;
if(k==0&&n>0) return;
if(k>0&&n==0) return;
if(k<0||n<0) return;
dfs(num+1,k,n,tmp);
if(n-num>=0){
tmp[tmpSize++] = num;
dfs(num+1,k-1,n-num,tmp);
tmpSize--;
}
}
这里面有个关键点,if(num>9)这个判断语句必须在if(k==0&&n==0)之后。因为在执行这句语句时
if(n-num>=0){
tmp[tmpSize++] = num;
dfs(num+1,k-1,n-num,tmp);
tmpSize--;
}
如果此时num=9,k=1,n=9,那么dfs中的参数分别为10,0,0,tmp,显然tmp中的数组序列已经满足了题目要求。
完整代码如下:
int ansSize;
int* Colunm_ans;
int tmpSize;
int**ans;
void dfs(int num,int k, int n, int*tmp){
if(k==0&&n>0) return;
if(k>0&&n==0) return;
if(k<0||n<0) return;
if(k==0&&n==0){
printf("?????");
int*tmpAns = (int*)malloc(sizeof(int)*1001);
for(int i = 0 ; i < tmpSize ; i++){
tmpAns[i] = tmp[i];
}
ans[ansSize] = tmpAns;
Colunm_ans[ansSize++] = tmpSize;
return;
}
if(num>9) return;
dfs(num+1,k,n,tmp);
if(n-num>=0){
tmp[tmpSize++] = num;
dfs(num+1,k-1,n-num,tmp);
tmpSize--;
}
}
int** combinationSum3(int k, int n, int* returnSize, int** returnColumnSizes) {
ans = (int**)malloc(sizeof(int*)*1001);
Colunm_ans = (int*)malloc(sizeof(int)*1001);
ansSize = 0;
int tmp[10];
dfs(1,k,n,tmp);
*returnSize = ansSize;
*returnColumnSizes = Colunm_ans;
printf("%d",tmpSize);
return ans;
}