解题思路:

创建一个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分

0 人评分

C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:

一点编程也不会写的:零基础C语言学练课程

解决困扰你多年的C语言疑难杂症特性的C语言进阶课程

从零到写出一个爬虫的Python编程课程

只会语法写不出代码?手把手带你写100个编程真题的编程百练课程

信息学奥赛或C++选手的 必学C++课程

蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程

手把手讲解近五年真题的蓝桥杯辅导课程

评论列表 共有 0 条评论

暂无评论