題目描述
牛客幼兒園的小朋友課間操時間需要按照學號從小到大排隊,但是他們太小了只能站成一列順序卻不對,現在幼兒園的阿姨需要幫忙交換小朋友的位置讓他們最終有序,阿姨希望能儘快完成交換操作,問最少需要交換多少次,才能使得小朋友們從小到大排好。
注意:每個小朋友的學號不同,但是未必連續,因爲可能有小朋友請假了沒有來。
輸入描述:
第一行一個整數 N。
接下來 N 行每行一個整數,爲小朋友們的隊列。
輸出描述:
一個整數表示小朋友們的最小交換次數。
示例1
輸入
3
2
1
3
輸出
1
備註:
N≤100000,其他整數均≤10^9
舉個例子
num:1 2 3 4 5
5 4 3 2 1
我們可以發現5,1雖然不在自己應該在的位置,但是如果把它們兩個看成整體,對於整個序列來說它們佔據了排好序後5,1應該在的位置,所以對於整個序列來說是有序的,它們只是自身內部無序而已。5應該到1處,1應該到5處,形成了一個循環,所以可以將它們抽象成一個環,環內換序就可以了。
對於一個含有n個元素的循環節來說,要使其有序,要交換n-1次(前面都排好了,最後一個數自然有序就不用排了)。
上例中3在原本就在的位置,可以看成一個元素的循環節。
我們可以推斷出有一個循環節,就可以少交換一次,因爲n個元素的循環節,只需交換n-1次即可有序。
那麼對於整個序列來說,最少交換次數爲 元素總數-循環節個數。
ac:代碼
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+100;
using namespace std;
int getMinSwaps(vector<int> &A)
{
vector<int> B(A);
sort(B.begin(), B.end());
map<int, int> m;
int len = (int)A.size();
for (int i = 0; i < len; i++)
{
m[B[i]] = i;
}
int loops = 0;
vector<bool> flag(len, false);
for (int i = 0; i < len; i++)
{
if (!flag[i])
{
int j = i;
while (!flag[j])
{
flag[j] = true;
j = m[A[j]];
}
loops++;
}
}
return len - loops;
}
vector<int> num;
int main()
{
int n;
for(cin>>n;n;n--)
{
int x;
cin>>x;
num.push_back(x);
}
int res = getMinSwaps(num);
cout << res << '\n';
ststem("pause");
return 0;
}