zoukankan      html  css  js  c++  java
  • (笔试题)和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.

  • 相关阅读:
    SQL2008-显示表大小行数
    SQL2008-备份SQL数据库的语句
    SQL2008-截取字段函数
    SQL2008-字符转数字CAST和CONVERT
    SQL2008-查询库中是否存在某表
    SQLServer 2000个人版下载
    SQL2008-不同数据库之间的触发器
    SQL2008--行号的得到
    Microsoft Visual Stduio 2005 Ent安装报错解决方法
    zlib快速编译脚本
  • 原文地址:https://www.cnblogs.com/AndyJee/p/4583600.html
Copyright © 2011-2022 走看看