题目 <https://leetcode-cn.com/problems/combination-sum-ii/>
日常回溯法
只要题目是返回所有结果的,一般是回溯法;如果是返回有多少解的,就是动态规划了
因为要判断不能重复,所以需要先排序,之后回溯的时候跳过重复值
/**
* Return an array of arrays of size *returnSize.
* The sizes of the arrays are returned as *returnColumnSizes array.
* Note: Both returned array and *columnSizes array must be malloced, assume caller calls free().
*/
int **returnNums;
int *returnColSizes;
int returnLen;
void sort(int *nums,int numsSize){
int left,right,mid,k;
mid = 0;left=1,right=numsSize-1;
if(left>right){
return;
}
while(left<=right){
while(left<=right&&nums[mid]<nums[right]) right--;
if(left>right) break;
k = nums[mid];
nums[mid] = nums[right];
nums[right] = k;
mid = right;
right--;
while(left<=right&&nums[mid]>nums[left]) left++;
if(left>right) break;
k = nums[mid];
nums[mid] = nums[left];
nums[left] = k;
mid = left;
left++;
}
sort(nums,mid);
sort(nums+mid+1,numsSize-mid-1);
}
void search(int* candidates, int candidatesSize,int target,int sum,int *tmp,int tmp_len,int index){
if(sum > target){
return;
}
if(sum == target){
returnColSizes[returnLen] = tmp_len;
returnNums[returnLen] = malloc(sizeof(int)*tmp_len);
memcpy(returnNums[returnLen],tmp,sizeof(int)*tmp_len);
returnLen++;
return;
}
int i,j;
for(i=index;i<candidatesSize;){
tmp[tmp_len] = candidates[i];
search(candidates,candidatesSize,target,sum + candidates[i],tmp,tmp_len+1,i+1);
j = candidates[i];
while(i<candidatesSize&&candidates[i]==j) i++;//跳过重复值
}
}
int** combinationSum2(int* candidates, int candidatesSize, int target, int* returnSize, int** returnColumnSizes){
sort(candidates,candidatesSize);
returnNums = malloc(sizeof(int**) * 10000);
returnColSizes = malloc(sizeof(int*) * 10000);
returnLen = 0;
int *tmp = malloc(sizeof(int) * candidatesSize);
search(candidates,candidatesSize,target,0,tmp,0,0);
free(tmp);
*returnSize = returnLen;
*returnColumnSizes = returnColSizes;
return returnNums;
}