力扣剑指offer38字符串的排列详细解答c语言
修改某大佬的代码
int is_repeat(char* chare_string,int start,int end){
for(;start<end;start++){
if(chare_string[start]==chare_string[end]) return 1;
}
return 0;
}
void swap(char* chare_string,int i,int j){
char tmp=chare_string[i];
chare_string[i]=chare_string[j];
chare_string[j]=tmp;
}
void dfs(char* chare_string,int head,int length,char** res,int* returnSize){
if(head==length-1){
char* tmp=(char*)malloc(sizeof(char)*(length+1));
strcpy(tmp,chare_string);
res[(*returnSize)++]=tmp;
}
for(int i=head;i<length;i++){
if(is_repeat(chare_string,head,i)){
continue;
}
swap(chare_string,head,i);
dfs(chare_string,head+1,length,res,returnSize);
swap(chare_string,head,i);
}
}
char** permutation(char* s, int* returnSize){//返回值为指向字符指针的指针
int length=strlen(s);
*returnSize=0;
if(s==NULL) return NULL;
int size=1;
for(int i=1;i<length+1;i++) size*=i;
char** res=(char*)malloc((size+1)*sizeof(char*));
dfs(s,0,length,res,returnSize);
return res;
}
上述是答案:下面进行分块分析;
首先对各个变量名进行解释:
chare_string指的是被操作的字符串;
函数dfs()里面head为头节点即被操作的同一行节点;
res是一个指向字符串指针的指针;也是最后一个操作函数的返回值;
returnSize初始是0,最终变成了排序的总种类。
这里用到了深度优先搜索递归的思想;
下面是我的个人见解:
这里插入力扣上找到的比较详细的图了
这是力扣上的图解,只能写出所有字母都不同的情况;
下面是有相同字母的图解
下面是比较难理解的部分了:
我想swap以及is_repeat不用介绍了吧。
直接到dfs()
首先if(head==length-1){
char* tmp=(char*)malloc(sizeof(char)*(length+1));
strcpy(tmp,chare_string);
res[(*returnSize)++]=tmp;
}
这个操作虽然放在第一行但是确实递归到最后一步的操作。将经过多次dfs操作后的chare_string开辟一个tmp空间储存,又因为res[returnsize]为指向字符串的指针,则指向tmp;
for(int i=head;i<length;i++){
if(is_repeat(chare_string,head,i)){
continue;
}
这个则是判断同一行节点是否存在相同的情况:如果存在可以直接跳过。因为下面的操作是交换这两者进行下一行的遍历。(如果不跳过会导致重复的结果,于题不符合)
swap(chare_string,head,i);
dfs(chare_string,head+1,length,res,returnSize);
swap(chare_string,head,i);
最后第一个swap是交换同行但是值不相同的字母顺序然后dfs交换后遍历下一行,最后一个swap则是重新换回来。再通过for语句判断与下一个字母是否相同,然后再经行上述过程。