2020年牛客算法入門課練習賽1 -E 交換(水題,求循環節)

題目傳送門

題目描述

牛客幼兒園的小朋友課間操時間需要按照學號從小到大排隊,但是他們太小了只能站成一列順序卻不對,現在幼兒園的阿姨需要幫忙交換小朋友的位置讓他們最終有序,阿姨希望能儘快完成交換操作,問最少需要交換多少次,才能使得小朋友們從小到大排好。
注意:每個小朋友的學號不同,但是未必連續,因爲可能有小朋友請假了沒有來。
輸入描述:
第一行一個整數 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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章