(笔试题)和0交换的排序

题目:

一个整数组里包含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.

posted @ 2015-06-17 16:07  AndyJee  阅读(4555)  评论(2编辑  收藏  举报