LeetCode 46. 全排列 Permutations (C语言)

版权声明:本文为博主原创文章,未经博主允许不得转载。 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;
}

猜你喜欢

转载自blog.csdn.net/hang404/article/details/85166151