《資料結構》10-排序6 Sort with Swap(0, i)
題目
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 (≤10
) 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 去交換其他位置的數,問如果要排序,至少需要交換多少次
用到表排序的思想:N個數字的排列由若干個獨立的環組成
什麼意思呢?比如:a[ ] = {3 5 2 1 7 0 4 6},將a陣列排序意思是要將正確的數放到正確的位置上去,a[0] = 3,而 3 的正確位置在 a[3],而 a[3]=1,1 的正確位置在 a[1],現在 a[1] = 5,5 的正確位置在 a[5],而 a[5] = 0,a[0] 的正確位置就是 0,和最開始的 a[0] = 3 接上了,這就被稱為一個環
由於是用 0 去交換其他值,所以總共有三種環:
- 環內只有一個元素,即該數已經在正確的位置上了,不需要交換,比如上面的 a[2] = 2
- 環內有 n 個元素,含 0,需要交換次數是:n-1 (每一個非 0 元素都要和 0 換一下)
- 環內有 n 個元素,不含 0,需要交換的次數是:n+1(把 0 換入換出+其餘 n-1 個非 0 元素和 0 換一下)
交換的次數就是各種環交換的總數
#include<iostream>
#include<vector>
using namespace std;
int main(){
int N;
cin>>N;
int tmp;
int sum = 0;
vector<int> A; // 存 N
vector<bool> flag;
for(int i=0;i<N;i++){
cin>>tmp;
A.push_back(tmp);
flag.push_back(false);
}
for(int i=0;i<N;i++){
if(A[i]!=i && !flag[i]){ // 沒被訪問過的單元環
int tmpSum = 0; // 計交換次數
int j = i;
do{
tmpSum++; // 每遇到一個數計數+1
flag[j] = true; // 標記環
if(!A[j]) // 如果遇到了 0,減去入環出環的兩次
tmpSum-=2;
j = A[j];
}while(j!=i);
tmpSum++; // 前面減去了 0,所以交換次數是當前數個數+1
sum += tmpSum;
}
}
cout<<sum<<endl;
return 0;
}