• 关于排序中最少交换次数的证明(置换环)


    关于排序中最少交换次数的证明(置换环)

    利用置换环可以进行证明。这里我只做感性的证明。

    问题

    对于长度为 n n n的数组 a a a a i ∈ N a_i\in N aiN a i a_i ai互不相同,每次操作可以选择任意两个位置 i , j i,j i,j交换 a i , a j a_i,a_j ai,aj,要求排序的最少交换次数。

    答案

    最少交换次数 c n t s w a p = n − c n t c i r c l e cnt_{swap}=n-cnt_{circle} cntswap=ncntcircle

    c n t c i r c l e cnt_{circle} cntcircle 就是数组中置换环的个数。

    方法

    首先我们对数组进行排序,然后进行映射到 [ 1 , n ] [1,n] [1,n]这个区间。

    比如 m ( a j ) = i m(a_j)=i m(aj)=i, 说明 a j a_j aj这个元素最终的位置应该在 i i i。可以理解为 j j j i i i连一条有向边。

    同时再开一个数组标记位置是否访问过。我们利用 m m m数组暴力找环的个数即可。

    时间复杂度: O ( n ) O(n) O(n)

    int getSwapCnt(vector<int>&a){
    	int n = a.size(),cnt=0;
    	vector<int>b(a);
    	sort(b.begin(),b.end());
    	unordered_map<int,int>m;
    	vector<bool>vis(n);
    	for(int i=0;i<n;i++) m[b[i]] = i;
    	for(int i=0;i<n;i++)
    		if(!vis[i]){
    			int j = i;
    			while(!vis[j]){
    				vis[j] = true;
    				j = m[a[j]];
    			}
    			cnt++;
    		}
    	return cnt;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    下面这个写法是反向的一个建边,可以允许 a i a_i ai相同。

    int a[N],b[N],n;
    bool vis[N];
    bool cmp(int &x,int &y){
    	return a[x]<a[y];
    }
    int getSwapCnt(){
    	int cnt=0;
    	for(int i=1;i<=n;i++) b[i] = i;
    	sort(b+1,b+n+1,cmp);
    	for(int i=1;i<=n;i++)
    		if(!vis[i]){
    			int j = i;
    			while(!vis[j]){
    				vis[j] = true;
    				j = b[j];
    			}
    			cnt++;
    		}
    	return cnt;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    简要证明

    显然如果有 n n n个环的话,说明此时已经排序好了。 c n t = n − n = 0 cnt=n-n=0 cnt=nn=0

    那么我们的目标就是要达到 n n n个环。

    每次我们可以选择一个环中的两个结点进行交换,这样环的个数会加1,变成两个。如下图所示:

    swap-node

    那么既然每次操作环个数加1,我们已经有 m m m个环了,那么要达到 n n n个环,显然最少次数是 n − m n-m nm次操作,加 n − m n-m nm个环。

    所以答案就是 n − m n-m nm

  • 相关阅读:
    jdk9模块化
    学习Java的第九天
    [docker]笔记-存储管理
    【电路基础1】电阻
    深度学习中的图像处理(基本介绍+示例代码)
    NLP 项目:维基百科文章爬虫和分类【01】 - 语料库阅读器
    spring cloud gateway Route配置
    Lock锁之公平锁与非公平锁(AQS实现原理)
    路由器和路由到底啥区别?
    预训练模型相对位置编码和绝对位置编码的通俗理解
  • 原文地址:https://blog.csdn.net/weixin_45750972/article/details/127833130