題目:
一個整數組里包含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.