解题思路
这题和78.子集不一样的地方在于:子集不能重复。我们需要先对集合进行排序,测试用例中其它样例不是按顺序排列的。
依然是回溯三部曲。子集也是组合问题,这次要求同一层上不可以选取相同的元素。
- 递归函数的参数:需要用到startIndex,因为在同一个集合里面,来记录搜索的起始位置;
- 终止条件:搜索的起始位置>=数组长度;
- 单层逻辑:从startIndex开始搜索nums。递归时i+1,因为这题不可以重复选取数组中的元素。 在里面做一个判断,如果
i>startIndex && nums[i] ==nums[i-1]
,就代表同一层中已经选取过了相同元素,continue跳出本次循环。
要注意的是copy()函数必须放在最前面,不然会漏掉集合为空的情况。
int *path;
int pathTop;
int **result;
int resultTop;
int *length;
//从小到大排序
int cmp(const void* a1, const void* a2) {
return *((int*)a1) - *((int*)a2);
}
void copy(){
int *temp = malloc(sizeof(int) *pathTop);
for(int i=0;i<pathTop;i++){
temp[i] = path[i];
}
result[resultTop] = temp;
length[resultTop++] = pathTop;
}
void backTrack(int *nums,int numsSize,int startIndex){
copy();
if(startIndex >=numsSize){
return;
}
for(int i=startIndex;i<numsSize;i++){
if(i>startIndex && nums[i]==nums[i-1]){
continue;
}else{
path[pathTop++] = nums[i];
backTrack(nums,numsSize,i+1);
pathTop--;
}
}
}
int** subsetsWithDup(int* nums, int numsSize, int* returnSize, int** returnColumnSizes){
path = malloc(sizeof(int) *numsSize);
result = malloc(sizeof(int*) *2000);
length = malloc(sizeof(int) *2000);
pathTop = resultTop = 0;
qsort(nums,numsSize,sizeof(int),cmp);
backTrack(nums,numsSize,0);
*returnSize = resultTop;
*returnColumnSizes = malloc(sizeof(int) *resultTop);
for(int i =0;i<resultTop;i++)
(*returnColumnSizes)[i] = length[i];
return result;
}