Given any permutation of the numbers {0, 1, 2,..., N-1}, it is easy to sort them in increasing order. But what if Swap(0, *)
is the ONLY operation that is allowed to use? For example, to sort {4, 0, 2, 1, 3} we may apply the swap operations in the following way:
Swap(0, 1) => {4, 1, 2, 0, 3}
Swap(0, 3) => {4, 1, 2, 3, 0}
Swap(0, 4) => {0, 1, 2, 3, 4}
Now you are asked to find the minimum number of swaps need to sort the given permutation of the first NN nonnegative integers.
Input Specification:
Each input file contains one test case, which gives a positive NN (≤10^5) followed by a permutation sequence of {0, 1, ..., N−1N-1}. All the numbers in a line are separated by a space.
Output Specification:
For each case, simply print in a line the minimum number of swaps need to sort the given permutation.
Sample Input:
10
3 5 7 2 6 4 9 0 8 1
Sample Output:
9
解析:
1、交换的次数最小,那么每次交换都应该把一个数换到它最终应该在的位置(这里把这个数叫做最终数)。
2、0如果在0号位,那么0必须换到一个位置(这个位置上的数不是最终数),这种情况会增加一次无用的交换,但这个交换也是必须的。
3、0不在0号位,那么要把0所在位置的最终数换到这个位置。
4、情况2需要找到0将要换到的位置,这里用set来存储这些位置(如果用遍历数组的方法来找,会超时)
5、情况3需要找到最终数所在的位置,这里使用mapA,即A数组的映射,来快速找到这个位置(用遍历数组的方法,同样会超时)
#include <cstdio>
#include <cstdlib>
#include <set>
using namespace std;
int A[100000], mapA[100000], N;
set<int> s;
void swap( int *a, int *b ) {
int tmp = *a;
*a = *b;
*b = tmp;
}
int main () {
int pos_zero, val_sub, pos_sub, cnt = 0;
scanf("%d", &N);
for ( int i = 0; i < N; i++ ) {
scanf("%d", &A[i]);
mapA[A[i]] = i; //记录映射
if ( A[i] != i && i != 0 ) //保存会被交换位置,0不保存(因为0会被多次交换)
s.insert(i);
if ( A[i] == 0 )
pos_zero = i;
}
while ( !s.empty() ) {
if ( pos_zero != 0 ) { //如果0不在自己的位置上
val_sub = mapA[pos_zero];
mapA[ A[pos_zero] ] = val_sub; //更新映射
mapA[ A[val_sub] ] = pos_zero;
swap( &A[pos_zero], &A[val_sub] );
cnt++;
s.erase(pos_zero); //pos_zero上的元素已确定,不会再被交换
pos_zero = val_sub; //更新0的位置
}
else {
if ( s.empty() )
break;
pos_sub = *s.begin();
mapA[ A[pos_zero] ] = pos_sub;
mapA[ A[pos_sub] ] = pos_zero;
swap( &A[pos_zero], &A[pos_sub] );
cnt++;
pos_zero = pos_sub;
}
}
printf("%d", cnt);
system("pause");
return 0;
}