题目
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 N nonnegative integers.
Input Specification:
Each input file contains one test case, which gives a positive N (<=105) followed by a permutation sequence of {0, 1, ..., N-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
即通过把0和某个数交换达到排序的效果。
直接按题意操作:
设0所在位置编号为i,则交换i和0;
直到i=0,寻找一个不符合要求的数,和0交换;
直到排序完毕。
但是这样找i所在的位置会比较麻烦,时间开销大。
在x次交换后0会回到编号为0的位置,而被交换的数也被换到相应的位置。
可以通过交换
(1)、编号为0的数
(2)、以编号为0的数为编号的那个数
直到0出现在编号为0的位置以达到相同的效果。然后依次扫描,直到获得一个没有在排好序的位置上的数,交换这个数和0。代价O(n)。
代码:
#include <iostream>
#include <stdio.h>
#include <algorithm>
using namespace std;
int main()
{
int n;
cin>>n;
int *data=new int[n]; //输入的数据
int id_zero; //0的位置
int not_sort=0; //最小的尚未排序的数
int count=0; //统计交换次数
int i;
for(i=0;i<n;i++) //输入数据
{
scanf("%d",&data[i]);
if(data[i]==0)
id_zero=i;
}
while(not_sort<n) //还有没拍好序的数
{
if(id_zero==0) //0在data[0]
{
while(not_sort<n&&data[not_sort]==not_sort) //找第一个没有排序的数
not_sort++;
if(not_sort>=n)
break;
swap(data[id_zero],data[not_sort]); //交换0和这个数
id_zero=not_sort;
count++;
}
else //0不在data[0]
{
swap(data[0],data[data[0]]); //!!!交换0位置上的数和编号为0位置上的数的数
count++; //!!!这个不是题义限定的交换,但是效果是相同的
if(data[0]==0)
id_zero=0;
}
}
cout<<count;
delete [] data;
return 0;
}