1. 程式人生 > >《資料結構》10-排序6 Sort with Swap(0, i)

《資料結構》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​​ 5

^5 ) 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 去交換其他值,所以總共有三種環:

  1. 環內只有一個元素,即該數已經在正確的位置上了,不需要交換,比如上面的 a[2] = 2
  2. 環內有 n 個元素,含 0,需要交換次數是:n-1 (每一個非 0 元素都要和 0 換一下)
  3. 環內有 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;
}