题目
Given a collection of numbers that might contain duplicates, return all possible unique permutations.
For example,
[1,1,2] have the following unique permutations:
[1,1,2], [1,2,1], and [2,1,1].
题目大意:就是在有重复数字的数组中,找出其所有的排列组合。
思路
思路与上篇博文基本相同,只是在存储之前,先判断结果中是否已经有相同的结果了,若存在相同的结果则不进行保存。
/**
* Return an array of arrays of size *returnSize.
* Note: The returned array must be malloced, assume caller calls free().
*/
int **result;
int index_my=0;
void swap(int *a,int *b){
int temp=*a;
*a=*b;
*b=temp;
}
int **my_premute(int *nums,int k,int length){
if(nums==NULL||length<1){
return NULL;
}
if(k==length){//其中的一种情况,保存
//检查下result是否已经有了此结果,如果存在则不再加入进行
bool isExist=false;
for(int i=0;i<index_my;i++){
int j;
for( j=0;j<length;j++){
if( result[i][j]!=nums[j]){//不相同就跳出进行下一次循环
break;
}
}
if(j==length){//这种情况就说明有重复的
isExist=true;
break;
}
}
if(!isExist){//不存在才开始存储
result[index_my]=(int *)malloc(length*sizeof(int));
if(result[index_my]==NULL){
exit(EXIT_FAILURE);
}
for(int k=0;k<length;k++){
result[index_my][k]=nums[k];
}
index_my++;
}
}
else{
for(int i=k;i<length;i++){
if(i!=k&&nums[i]==nums[k])//相同则就不交换,仅仅考这条语句是没法去掉全部重复的。
continue;
swap(&nums[i],&nums[k]);//都与第k个元素进行交换,然后进行下一轮的递归。
my_premute(nums,k+1,length);
swap(&nums[i],&nums[k]);
}
}
}
int** permuteUnique(int* nums, int numsSize, int* returnSize) {
if(nums==NULL||numsSize<1){
return NULL;
}
int num=1;
for(int i=1;i<=numsSize;i++){
num*=i;
}
index_my=0;
result=(int **)malloc(num*sizeof(int *));
if(result==NULL){
printf("malloc fail");
exit(EXIT_FAILURE);
}
my_premute(nums,0,numsSize);
*returnSize=index_my;
return result;
}
//测试代码
int main(void){
int k;
while(scanf("%d",&k)!=EOF){
int *arr=(int *)malloc(k*sizeof(int));
if(arr==NULL){
exit(EXIT_FAILURE);
}
for(int i=0;i<k;i++){
scanf("%d",arr+i);
}
int returnSize=0;
int **temp=permuteUnique(arr,k,&returnSize);
for(int i=0;i<returnSize;i++){
for(int j=0;j<k;j++){
printf("%d ",temp[i][j]);
}
printf("\n");
}
printf("\n");
}
}
遇到的问题
1、报这样一个编译错误: parameter ‘k’ has just a forward declaration
第一次遇到这样的错误,因此就记录下来了,问题的来源如图所示:即将参数k后面的逗号误写成了分号。
2、
原以为可以通过如下代码就可以将所有重复的结果过滤掉。,但是不行。只能过滤一部分。
for(int i=k;i<length;i++){
if(i!=k&&nums[i]==nums[k])//相同则就不交换,仅仅考这条语句是没法去掉全部重复的。
continue;
swap(&nums[i],&nums[k]);//都与第k个元素进行交换,然后进行下一轮的递归。
my_premute(nums,k+1,length);
swap(&nums[i],&nums[k]);
}
}
解决办法:检查下result是否已经有了此结果,如果存在则不再加入进行
最后的AC结果如下:
从结果可以看出,用时72ms,虽然AC了,但是用时实在是太长,需要改进。