解题思路:
创建一个visited数组来标记已经访问过的位置
遍历数组,对于每个未访问的位置,开始寻找循环
在循环中,从当前位置开始,按照"当前元素的值应该放在哪个位置"的规则追踪整个循环
对于每个长度为k的循环,需要k-1次交换
将所有循环的交换次数相加得到总的最小交换次数
注意事项:
参考代码:
#include <stdio.h>
#include <stdlib.h>
int minSwaps(int arr[], int n) {
// 创建位置数组,记录每个编号应该在的位置
int *pos = (int *)malloc((n + 1) * sizeof(int));
int *visited = (int *)calloc(n, sizeof(int));
// 记录每个元素的位置
for (int i = 0; i < n; i++) {
pos[arr[i]] = i;
}
int swaps = 0;
for (int i = 0; i < n; i++) {
// 如果当前位置已经是正确的书,或者已经访问过,则跳过
if (visited[i] || arr[i] == i + 1) {
continue;
}
// 开始寻找循环
int cycle_size = 0;
int j = i;
while (!visited[j]) {
visited[j] = 1;
// 当前元素arr[j]应该放在位置arr[j]-1
j = pos[j + 1]; // 找下一个位置
cycle_size++;
}
// 对于长度为k的循环,需要k-1次交换
if (cycle_size > 0) {
swaps += (cycle_size - 1);
}
}
free(pos);
free(visited);
return swaps;
}
int main() {
int n;
// 读取输入
if (scanf("%d", &n) != 1) {
return 1;
}
int *arr = (int *)malloc(n * sizeof(int));
for (int i = 0; i < n; i++) {
if (scanf("%d", &arr[i]) != 1) {
free(arr);
return 1;
}
}
// 计算最小交换次数
int result = minSwaps(arr, n);
printf("%d\n", result);
free(arr);
return 0;
}
0.0分
0 人评分
C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:
一点编程也不会写的:零基础C语言学练课程
解决困扰你多年的C语言疑难杂症特性的C语言进阶课程
从零到写出一个爬虫的Python编程课程
只会语法写不出代码?手把手带你写100个编程真题的编程百练课程
信息学奥赛或C++选手的 必学C++课程
蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程
手把手讲解近五年真题的蓝桥杯辅导课程
发表评论 取消回复