版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/hang404/article/details/85166151
题目描述:
给定一个没有重复数字的序列,返回其所有可能的全排列。
示例:
输入: [1,2,3]
输出:
[
[1,2,3],
[1,3,2],
[2,1,3],
[2,3,1],
[3,1,2],
[3,2,1]
]
题目解答:
方法1:回溯
使用循环+递归,并利用标记数组,来标记每个数字是否使用过,使用过则跳过,没使用过则可以使用,并且要记得取消标记。
运行时间4ms,代码如下。
/**
* Return an array of arrays of size *returnSize.
* Note: The returned array must be malloced, assume caller calls free().
*/
void dfs(int*** result, int* size, int* before, int bef, int n, int* nums, bool* flag) {
if(bef == n) {
(*size)++;
result[0] = (int**)realloc(result[0], *size * sizeof(int*));
result[0][*size - 1] = (int*)malloc(n * sizeof(int));
memcpy(result[0][*size - 1], before, n * sizeof(int));
return;
}
int i = 0;
for(i = 0; i < n; i++) {
if(!flag[i]) {
flag[i] = true;
before[bef] = nums[i];
dfs(result, size, before, bef + 1, n, nums, flag);
flag[i] = false;
}
}
}
int** permute(int* nums, int numsSize, int* returnSize) {
int** result = NULL;
int* before = (int*)malloc(numsSize * sizeof(int));
bool* flag = (bool*)calloc(numsSize, sizeof(bool));
dfs(&result, returnSize, before, 0, numsSize, nums, flag);
free(before);
free(flag);
return result;
}
或者使用交换法,将start
及其之后的依次与start
交换,进行递归,注意要交换回去。
运行时间4ms,代码如下。
/**
* Return an array of arrays of size *returnSize.
* Note: The returned array must be malloced, assume caller calls free().
*/
void dfs(int*** result, int* size, int* before, int start, int n) {
if(start == n) {
(*size)++;
result[0] = (int**)realloc(result[0], *size * sizeof(int*));
result[0][*size - 1] = (int*)malloc(n * sizeof(int));
memcpy(result[0][*size - 1], before, n * sizeof(int));
}
int i = 0, temp = 0;
for(i = start; i < n; i++) {
temp = before[i];
before[i] = before[start];
before[start] = temp;
dfs(result, size, before, start + 1, n);
before[start] = before[i];
before[i] = temp;
}
}
int** permute(int* nums, int numsSize, int* returnSize) {
int** result = NULL;
int* before = (int*)malloc(numsSize * sizeof(int));
bool* flag = (bool*)calloc(numsSize, sizeof(bool));
memcpy(before, nums, numsSize * sizeof(int));
dfs(&result, returnSize, before, 0, numsSize);
free(before);
return result;
}
方法2:迭代法
有点类似于动态规划,假设我们现在已经存储好前n - 1
个数字的所有排列情况,则我们任取一种排列,第n
个数字插入其中,则有n
个位置可以插入,所以对每个排列情况都进行这样的插入操作即可。
运行时间4ms,代码如下。
/**
* Return an array of arrays of size *returnSize.
* Note: The returned array must be malloced, assume caller calls free().
*/
int** permute(int* nums, int numsSize, int* returnSize) {
int i = numsSize, sum = 1;
int j = 0, k = 0, last = 0;
while(i) {
sum *= i;
i--;
}
int* temp = (int*)malloc(numsSize * sizeof(int));
int** result = (int**)malloc(sum * sizeof(int*));
for(i = 0; i < sum; i++)
result[i] = (int*)malloc(numsSize * sizeof(int));
result[0][0] = nums[0];
sum = 1;
for(i = 1; i < numsSize; i++) {
last = sum;
for(j = 0; j < last; j++) {
result[j][i] = nums[i];
}
for(j = 0; j < last; j++) {
memcpy(temp, result[j], i * sizeof(int));
for(k = i - 1; k >= 0; k--) {
temp[k + 1] = temp[k];
temp[k] = nums[i];
memcpy(result[sum++], temp, (i + 1) * sizeof(int));
}
}
}
free(temp);
*returnSize = sum;
return result;
}