题干:
输入一个字符串,打印出该字符串中字符的所有排列。
你可以以任意顺序返回这个字符串数组,但里面不能有重复元素。
示例:
输入:s = "abc"
输出:["abc","acb","bac","bca","cab","cba"]
限制:
1 <= s 的长度 <= 8
解题思路:
本身是一个全排列的问题,字符型全排列较之数字型全排列稍微有些麻烦,但是基本思路一致,采用回溯思想,将每个数字分别放到第一位,并将后面的数字进行全排列。
需要注意的是,如果输入abb类型的字符,全排列会出现重复,去重的方法主要通过遍历字符串,若发现之后有字符相同,则跳过。
另外注意字符串的长度问题需要加上‘\0’
代码实现:
int count = 0; //存储数量count
//char **arr = NULL;
void swap(char* s, int i, int j){ //定义一个交换函数
char tmp = s[j];
s[j] = s[i];
s[i] = tmp;
}
bool judge(char* s, int start, int end){ //当字母为abb时,全排序可能出现重复,因此需要去重
int i;
for (i = start; i < end; i++){ //当前的数字分别与不等于它的数字交换,1不和1换,2不和2换
if (s[i] == s[end]){
return true;
}
}
return false;
}
void perm(char* s, int p, char** arr, int len){ //进行全排列
if (p == len){ //设置停止条件,当p指向字符串的末尾时截止
s[len] = '\0'; //给当前s添加截止符'\0'
memcpy(arr[count], s, len); //将s赋值给二维数组arr
count++; //排列数量加1
return;
}
int i;
for (i = p; i < len; i++){ //依次将每个数置于第一位
if (judge(s, p, i)){ //判断是否重复
continue;
}
swap(s, p, i); //把本轮指向的数放到第一位
perm(s, p + 1, arr, len); //对剩下的数进行全排列
swap(s, p, i); //再把原本的第一位数换回来
}
}
char** permutation(char* s, int* returnSize){
int total = 1; //total存储N个数的全排列情况为N!
int len = strlen(s);
int i;
count = 0;
for (i = 2; i <= len; i++){
total *= i;
}
char** arr = (char**)malloc(sizeof(char*) * total); //申请一个能够存储N!个的内存
for (i = 0; i < total; i++){
arr[i] = (char*)calloc(len + 1, sizeof(char)); //申请每一行存储的内存数
}
perm(s, 0, arr, len); //进行全排列
* returnSize = count;
return arr;
}