本专栏持续输出数据结构题目集,欢迎订阅。

文章目录

题目

将 { 0, 1, 2, …, n−1 } 的任意一个排列进行排序并不困难,这里加一点难度,要求你只能通过一系列的 Swap(0, *) —— 即将一个数字与 0 交换 —— 的操作,将初始序列增序排列。例如对于初始序列 { 4, 0, 2, 1, 3 },我们可以通过下列操作完成排序:

  • Swap(0, 1) ⟹ { 4, 1, 2, 0, 3 }
  • Swap(0, 3) ⟹ { 4, 1, 2, 3, 0 }
  • Swap(0, 4) ⟹ { 0, 1, 2, 3, 4 }

本题要求你找出将前 n 个非负整数的给定排列进行增序排序所需要的最少的与 0 交换的次数。

输入格式:
输入在第一行给出正整数 n (≤10^5);随后一行给出{ 0, 1, 2, …, n−1 } 的一个排列。数字间以空格分隔。

输出格式:
在一行中输出将给定序列进行增序排序所需要的最少的与 0 交换的次数。

输入样例:
10
3 5 7 2 6 4 9 0 8 1

输出样例:
9

代码

#include <stdio.h>
#include <stdlib.h>

int main() {
    int n;
    scanf("%d", &n);
    
    int *arr = (int *)malloc(n * sizeof(int));
    for (int i = 0; i < n; i++) {
        scanf("%d", &arr[i]);
    }
    
    int *visited = (int *)calloc(n, sizeof(int));  // 标记元素是否已处理
    int total_swaps = 0;
    
    for (int i = 0; i < n; i++) {
        if (!visited[i] && arr[i] != i) {  // 找到未处理的循环
            int cycle_len = 0;
            int current = i;
            int has_zero = 0;  // 标记循环中是否包含0
            
            // 遍历当前循环
            while (!visited[current]) {
                visited[current] = 1;
                cycle_len++;
                if (arr[current] == 0) {
                    has_zero = 1;
                }
                current = arr[current];  // 移动到下一个元素
            }
            
            // 根据循环是否包含0计算交换次数
            if (has_zero) {
                total_swaps += (cycle_len - 1);
            } else {
                total_swaps += (cycle_len + 1);
            }
        }
    }
    
    printf("%d\n", total_swaps);
    
    return 0;
}
Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐