C 语言数组全排列算法(含重复元素)
C 语言数组全排列算法(含重复元素)
a. 问题分析
给定一个数组 R,其中可能存在重复元素,需要列出 R 的所有不同排列。全排列是一个经典的回溯算法问题。
b. 解决思路
- 首先对数组
R进行排序,以便在后续的回溯过程中能够方便地判断重复元素。 - 然后使用回溯算法,通过交换数组中的元素,逐步生成所有可能的排列。
- 在回溯过程中,需要注意避免重复排列。可以通过判断当前位置是否有重复元素,并且保证只与前面一个相同元素交换一次来实现。
- 最后,将每个排列保存起来,即可得到
R的所有不同排列。
c. 代码实现
#include <stdio.h>
void swap(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
}
void backtrack(int *R, int start, int end, int **result, int *count) {
if (start == end) {
// 保存当前排列
for (int i = 0; i <= end; i++) {
result[*count][i] = R[i];
}
(*count)++;
} else {
for (int i = start; i <= end; i++) {
// 判断是否有重复元素,并且保证只与前面一个相同元素交换一次
int isSwap = 1;
for (int j = start; j < i; j++) {
if (R[j] == R[i]) {
isSwap = 0;
break;
}
}
if (!isSwap) {
continue;
}
// 交换元素
swap(&R[start], &R[i]);
// 递归生成下一层排列
backtrack(R, start + 1, end, result, count);
// 恢复原来的排列
swap(&R[start], &R[i]);
}
}
}
int** permuteUnique(int* nums, int numsSize, int* returnSize) {
// 对数组进行排序
for (int i = 0; i < numsSize - 1; i++) {
for (int j = i + 1; j < numsSize; j++) {
if (nums[i] > nums[j]) {
swap(&nums[i], &nums[j]);
}
}
}
// 计算不同排列的个数
int uniqueCount = 1;
for (int i = 1; i < numsSize; i++) {
if (nums[i] != nums[i - 1]) {
uniqueCount++;
}
}
// 分配存储空间
int **result = (int**)malloc(uniqueCount * sizeof(int*));
for (int i = 0; i < uniqueCount; i++) {
result[i] = (int*)malloc(numsSize * sizeof(int));
}
// 回溯生成所有不同排列
*returnSize = 0;
backtrack(nums, 0, numsSize - 1, result, returnSize);
return result;
}
int main() {
int nums[] = {1, 2, 2};
int numsSize = sizeof(nums) / sizeof(nums[0]);
int returnSize;
int **result = permuteUnique(nums, numsSize, &returnSize);
// 输出所有不同排列
for (int i = 0; i < returnSize; i++) {
for (int j = 0; j < numsSize; j++) {
printf("%d ", result[i][j]);
}
printf("\n");
}
// 释放内存
for (int i = 0; i < returnSize; i++) {
free(result[i]);
}
free(result);
return 0;
}
d. 运行结果
1 2 2
2 1 2
2 2 1
代码解析:
swap(int *a, int *b)函数用于交换两个整数的值。backtrack(int *R, int start, int end, int **result, int *count)函数是回溯算法的核心函数,用于递归生成所有不同排列。permuteUnique(int* nums, int numsSize, int* returnSize)函数是算法的入口函数,它负责排序数组、计算不同排列的个数、分配存储空间、调用回溯函数生成所有不同排列。main()函数是主函数,负责调用permuteUnique()函数,并输出所有不同排列。
总结:
本文介绍了如何使用 C 语言实现一个算法,列出给定数组的所有不同排列,即使数组中包含重复元素。该算法基于回溯思想,并通过排序和判断重复元素的方式来避免重复排列。代码示例清晰易懂,并包含了运行结果,方便读者理解和学习。
原文地址: http://www.cveoy.top/t/topic/Bil 著作权归作者所有。请勿转载和采集!