将 { 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
改不出来了
//利用表排序来达到
//表排序中的独立环分为三类:
/*
第一种:只有一个元素,不需要交换;
第二种,环里有n1个元素,包括0,需要n1-1次交换;
第三种:第i个环里有ni个元素,不包括0:先把0换到环里,再进行(ni+1)-1次交换——一共是ni+1次交换;
如果N个元素的序列中包含S个单元环,K个多元环,则交换的次数为N-S+K-2次
*/
#include<iostream>
#include<stdio.h>
using namespace std;
#define MAX 100001
void dfs(int x);
int A[MAX];
int T[MAX];
int n;
int cnt=0;
int fll=0;
int main(){
cin>>n;
int s=0;
for(int i=0;i<n;i++){
scanf("%d",&A[i]);
T[A[i]]=i; //元素i在A[T[i]]中存放
if(A[i]==i){s++;} //独立的环个数
}
for(int i=0;i<n;i++){
if(T[i]!=i){
//printf("T[%d]=%d ",i,T[i]);
fll=A[i];
cnt++; //cnt个多元环
dfs(i);
}
}
int num=n-s+cnt-2;
cout<<num<<endl;
}
void dfs(int x){
//printf("x=%d ",x);
if(T[x]!=x){
int tmp=T[x];
A[x]=A[T[x]];
if(T[T[x]]==x){
A[x]=fll;
}
T[x]=x;
dfs(tmp);
}
else return ;
}