題目:
一個整數組里包含0-(n-1)的排列 (0到(n-1)恰好只出現一次),如果每次只允許把任意數和0交換,求排好順序至少交換多少次。
思路:
這是組合數學中的圈問題,可以把數組中的位置關系看成圖的拓撲關系。
例如A[3]={2,0,1},2在0的位置,0在1的位置,1在2的位置,那么把它們畫成圖的拓撲結構的話,就是一個環(圈),即2->0->1->2。
這樣的條件(排列成環(圈))用文字描述為:1、位置和位置上的數字或字符存在一一對應關系;2、每個數字或字符都不在自己應有的位置上;
上例我們通過交換1和0,再交換2和0,即可正確排序,次數為2.
一個排序總可以划分為不同的環(圈),獨立成圈的不需要交換;
總結滿足上述條件的規律:
- 一個長度為m的圈,如果包含0,則交換(m -1)次可以恢復所有的數到原位
- 一個長度為m的圈,如果不包含0,則交換(m+ 1) 次可以恢復所有的數到原位
代碼:
#include <iostream>
using namespace std;
int circle(int A[],bool isvisited[],int x){
int count=0;
while(!isvisited[x]){
count++;
isvisited[x]=true;
x=A[x];
}
if(count==0)
return 0;
else
return count-1;
}
int main()
{
int A[]={1,3,2,4,6,5,0};
int n=sizeof(A)/sizeof(A[0]);
bool isvisited[n];
for(int i=0;i<n;i++)
isvisited[i]=false;
int count=0;
for(int i=0;i<n;i++){
count+=circle(A,isvisited,A[i]);
}
cout << count << endl;
return 0;
}
運行結果:
4
該數組划分為3個圈,其中2和5獨立成圈,無需交換,而其他五個數成圈,1->3->4->6->0->1,交換次數為5-1=4.
