题目
找出所有相加之和为 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,没有有效的组合。
代码
int *path;
int pathTOP;
int**ans;
int ansTOP;
void backtracking(int targetsum,int k,int sum,int satrtindex)
{
int i =0;
if(sum> targetsum)//剪枝操作
{
return;
}
if(k==pathTOP)
{
if(sum == targetsum)
{
int *temp=(int*)malloc(sizeof(int)*k);
for(i=0;i<k;i++)
{
temp[i]=path[i];
}
ans[ansTOP++]=temp;
}
return;
}
for(i=satrtindex;i<=9-(k-pathTOP)+1;i++)
{
sum+=i;
path[pathTOP++]=i;
backtracking( targetsum,k,sum,i+1);
sum-=i;
pathTOP--;
}
}
int** combinationSum3(int k, int n, int* returnSize, int** returnColumnSizes){
path=(int*)malloc(sizeof(int)*k);
ans=(int**)malloc(sizeof(int*)*10000);
pathTOP=0;
ansTOP=0;
int sum=0;
backtracking(n,k,sum,1);
*returnSize=ansTOP;
*returnColumnSizes=(int*)malloc(sizeof(int)*(*returnSize));
int i=0;
for(i=0;i<(*returnSize);i++)
{
(*returnColumnSizes)[i]=k;
}
return ans;
}
过程分析
设置在外层return返回的原因
当 取 1 2 3 时 k=3,sum=1+2+3=6时,由于n题中要求符合n=7,而 sum<tragsum 对应进入递归终止条件中, 但tragsum<n所以需要在外面设置return 返回上一层, 此时的 sum 需要减去 这一层的 i的值3 即 sum=sum-3=1+2
正确传入
当取 1 2 4 时, 使用return返回到上一层后,取 4再次进入下一层 k=3,sum=1+2+4=7时,tragsum==sum,进入两层if循环后,将一维数组path的值 传入 ans二维数组中,返回时仍需要减去这一层i的值4即sum-4=1+2
剪枝操作
1.
当为 1 2 5时, k=3,sum=1+2+5=8时,tragsum>sum,进入if循环,返回到上一层 ,减去这一层i的值5 即 sum-5=1+2
2.
当取 1 2 3 4时,k=4,因为题中要求是k=3,所以不符合题意 为了删去不符合题意的枝条,所以在for循环中设置边界
剪枝操作范围的确定
1.
startindex默认为1,i=1开始, 假设 k=3,sum=7 pathTOP代表所选取的元素个数 (默认从0开始)
2.
k-pathTOP代表剩下还需要选取的元素个数 k=3 ,k-pathtOP=3
3.
n-i代表列表中的元素个数 n-i >= k-pathtOP
4.
i<=n-(k-pathTOP)+1 此时的i处于至多可以遍历的位置 因为 i默认从1开始,所以需要加上1,使其可以包括起始位置