交换最小次数 和一些排序方式
问题:洛谷P8637 交换瓶子
有 N个瓶子,编号 1∼N,放在架子上。
比如有 5 个瓶子:
2,1,3,5,4
要求每次拿起 2 个瓶子,交换它们的位置。
经过若干次后,使得瓶子的序号为:
1,2,3,4,5
对于这么简单的情况,显然,至少需要交换 2 次就可以复位。
如果瓶子更多呢?你可以通过编程来解决。
输入格式
第一行:一个正整数 N(N<10000),表示瓶子的数目。
第二行:N 个正整数,用空格分开,表示瓶子目前的排列情况。
输出格式
输出数据为一行一个正整数,表示至少交换多少次,才能完成排序。
思路:
不在规定位置上的用圈排序把它放到它应该呆的位置上。
圈排序只查看一下有多少需要排序,不进行排序。
#include<bits/stdc++.h> using namespace std; int a[10010],s,ans,n,k; void pencil(int l,int m)//递归 { if(s==k) { a[l]=0; return ; } s=a[m]; ans++; a[l]=0; return pencil(m,s); } int main() { cin>>n; for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int i=1;i<=n;i++) { if(i==a[i]||a[i]==0) continue; s=0; k=i; pencil(i,a[i]); a[i]=0; } cout<<ans; return 0; }
拓展
解决只能交换相邻两数的情况
逆序数
首先定义一个标准次序(例如对于n个不同的自然数,可规定从小到大为标准次序)。于是在这n个元素的任一排列中,当某两个元素的先后次序与标准次序不同时,就说有一个逆序。
例如在一个排列中,如果一对数的前后与大小顺序正好相反(即:前面的数大于后面的数),那么它们就称为一个逆序。一个排列中逆序的总数就称为这个排列的逆序数。根据逆序数
的奇偶可将排列分为奇排列和偶排列。
比如: 7 5 1 6 3 按从小到大为标准次序,逆序为7,5 7,1 7,6 7,3 5,1 5,3 6,3 逆序数为7
7,5 7,1 7,6 7,3 5 1 6 3 7
6,3 5,1 1 5 3 6 7
5,3 1 3 5 6 7 一共交换七次。
算法:归并算法
解决交换任意两个数,求最少交换次数
圈排序:(Cycle Sort)
不在排序后位置上的需要交换位置。
快速排序:O(nlog2n)
基本思想: 任取一个元素(如第一个)为中心,比它小的放在前面,大的放在后面
结果会被这个元素分成两部分,两部分再取第一个元素为中心,小的放在前面,大的放在后面。(递归,分而治之)
基数排序:适合多关键字排序
n:往桶里扔的时候要扔多少元素
计数排序:
7 2 3 6 4
比它小的数的个数 4 0 1 3 2,即为每个数在数组中的位置。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY