题目

Given any permutation of the numbers {0, 1, 2,…, N-1}, it is easy to sort them in increasing order. But what if Swap(0, *) is the ONLY operation that is allowed to use? For example, to sort {4, 0, 2, 1, 3} we may apply the swap operations in the following way:

Swap(0, 1) => {4, 1, 2, 0, 3}

Swap(0, 3) => {4, 1, 2, 3, 0}

Swap(0, 4) => {0, 1, 2, 3, 4}

Now you are asked to find the minimum number of swaps need to sort the given permutation of the first N nonnegative integers.

Input Specification:

Each input file contains one test case, which gives a positive N (<=105) followed by a permutation sequence of {0, 1, …, N-1}. All the numbers in a line are separated by a space.

Output Specification:

For each case, simply print in a line the minimum number of swaps need to sort the given permutation.

Sample Input:

10 3 5 7 2 6 4 9 0 8 1

Sample Output:

9

题目分析

已知N个任意排列的数字,要求最少交换次数对其排序(排序过程只能使用0与其他数字交换位置

解题思路

  1. 贪心算法:如果当前数字0在i号位置,找到数字i当前所处位置,将数字0和i交换

证明:

由于0必须参加交换操作,因此通过该策略,每步总是可以将一个非零的数回归本位。如果用0与其他不是该位置编号的数进行交换,显然会产生一个无效操作,因为后续操作中还是需要将刚才交换的数换回本位,因此该策略能将无效操作次数(与0交换的数没有回归本位的次数)降到最小,于是最优。

第一步: 0在7号位,因此将0与7交换,得到序列3502649781

第二步: 0在2号位,因此将0与2交换,得到序列3520649781

第三步: 0在3号位,因此将0与3交交换,得到序列0523649781

第四步: 0在0号位,因此将0与一个还未在本位的数字5交换,得到序列得到序列5023649781

第五步: 0在1号位,因此将0与1交换,得到序列5123649780

第六步: 0在9号位,因此将0与9交换,得到序列5123640789

第七步: 0在6号位,因此将0与6交换,得到序列5123046789

第八步: 0在4号位,因此将0与4交换,得到序列5123406789

第九步: 0在5号位,因此将0与5交换,得到序列0123456789

此时序列有序,总交换次数为9次。

//style="background-color: #FF8C00;"

  1. 定义数组int pos[N],记录数字所在位置(如:pos[i],表示数字i在pos[i]的位置)
  2. 哨兵为数字0,pos[0]=0,不一定排序已完成
    • pos[0]==0,但是排序未完成,将0需要与不在本位的数字交换(因为如果0与已回到本位的数字交换会导致交换次数变多),定义数字k初始化为1,记录当前不在本位的最小数字(避免每次都循环遍历数组,查找未回到本位的数字(复杂度为O(n^2)有两个点会超时))
    • pos[0]==0,已完成排序(如何检测已完成排序?--定义变量left记录除0以外不在自己本位数字的个数,left=0表示排序完成)

注意点

  1. 当0回到本位时,并不一定保证数字都已回到本位。此时需要找到一个未在本位的数字与0进行交换(如果选择已在本位的数字与0交换会导致交换次数增多)

Code

Code 01

  1. #include <iostream>
  2. #include <string>
  3. using namespace std;
  4. int main(int argc, char * argv[]) {
  5. int N,m,cnt=0;//cnt--总交换次数
  6. scanf("%d",&N);
  7. int pos[N]= {0};// pos[i]--数字i的位置为pos[i]
  8. int left=N-1; // 除0以外不在本位的数字
  9. for(int i=0; i<N; i++) {
  10. scanf("%d", &m);
  11. pos[m]=i; // 数字m在位置i
  12. if(m==i&&m!=0)left--; // 除0以外已在本位,left--
  13. }
  14. int k=1; //当前最小不在本位的数字,避免0在本位但排序未完成时,每次都需要遍历数组找未在本位的数字(复杂度O(n^2)会超时)
  15. while(left>0) {
  16. if(pos[0]==0) { //如果排序未完成,0已回到本位,将0与最小不在本位的k进行互换
  17. while(k<N) {
  18. if(pos[k]!=k) { //如果k不在本位
  19. swap(pos[0],pos[k]);
  20. cnt++; //无需left++,因为k本来就不再本位,0在本位但是left记录的是非0不在本位的数字个数
  21. break;
  22. }
  23. k++; //如果k在本位,向前找最小不在本位的k
  24. }
  25. }
  26. while(pos[0]!=0) { //0不在本位
  27. swap(pos[0],pos[pos[0]]);
  28. left--; //有一个数字回归本位
  29. cnt++;
  30. }
  31. }
  32. printf("%d",cnt);
  33. return 0;
  34. }

Code 02

  1. #include <iostream>
  2. #include <string>
  3. using namespace std;
  4. int main(int argc, char * argv[]) {
  5. int N,m,cnt=0;
  6. scanf("%d",&N);
  7. int pos[N]= {0};
  8. for(int i=0; i<N; i++) {
  9. scanf("%d", &m);
  10. pos[m]=i;
  11. }
  12. for(int i=0; i<N; i++) { //个人理解,这里处理不是很好,因为已遍历过的i不能保证其已回到本位
  13. if(pos[i]!=i) {
  14. while(pos[0]!=0) {
  15. swap(pos[0],pos[pos[0]]);
  16. cnt++;
  17. }
  18. if(pos[i]!=i) {
  19. swap(pos[0],pos[i]);
  20. cnt++;
  21. }
  22. }
  23. }
  24. printf("%d",cnt);
  25. return 0;
  26. }

PAT Advanced 1067 Sort with Swap(0,*) (25) [贪⼼算法]的更多相关文章

  1. PAT甲题题解-1067. Sort with Swap(0,*) (25)-贪心算法

    贪心算法 次数最少的方法,即:1.每次都将0与应该放置在0位置的数字交换即可.2.如果0处在自己位置上,那么随便与一个不处在自己位置上的数交换,重复上一步即可.拿样例举例:   0 1 2 3 4 5 ...

  2. 1067. Sort with Swap(0,*) (25)【贪心】——PAT (Advanced Level) Practise

    题目信息 1067. Sort with Swap(0,*) (25) 时间限制150 ms 内存限制65536 kB 代码长度限制16000 B Given any permutation of t ...

  3. PAT 甲级 1067 Sort with Swap(0, i) (25 分)(贪心,思维题)*

    1067 Sort with Swap(0, i) (25 分)   Given any permutation of the numbers {0, 1, 2,..., N−1}, it is ea ...

  4. 1067. Sort with Swap(0,*) (25)

    时间限制 150 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue Given any permutation of the num ...

  5. PAT (Advanced Level) 1067. Sort with Swap(0,*) (25)

    只对没有归位的数进行交换. 分两种情况: 如果0在最前面,那么随便拿一个没有归位的数和0交换位置. 如果0不在最前面,那么必然可以归位一个数字,将那个数字归位. 这样模拟一下即可. #include& ...

  6. PAT 1067. Sort with Swap(0,*)

    1067. Sort with Swap(0,*) (25)   Given any permutation of the numbers {0, 1, 2,..., N-1}, it is easy ...

  7. pat1067. Sort with Swap(0,*) (25)

    1067. Sort with Swap(0,*) (25) 时间限制 150 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue G ...

  8. 1067 Sort with Swap(0, i) (25 分)

    1067 Sort with Swap(0, i) (25 分) Given any permutation of the numbers {0, 1, 2,..., N−1}, it is easy ...

  9. PTA 1067 Sort with Swap(0, i) (贪心)

    题目链接:1067 Sort with Swap(0, i) (25 分) 题意 给定长度为 \(n\) 的排列,如果每次只能把某个数和第 \(0\) 个数交换,那么要使排列是升序的最少需要交换几次. ...

随机推荐

  1. 吴裕雄--天生自然C++语言学习笔记:C++ 运算符

    运算符是一种告诉编译器执行特定的数学或逻辑操作的符号.C++ 内置了丰富的运算符,并提供了以下类型的运算符: 算术运算符 关系运算符 逻辑运算符 位运算符 赋值运算符 杂项运算符 算术运算符 下表显示 ...

  2. 远程控制使用kill软件映射内网进行远程控制(9.28 第十四天)

    1.能ping通IP情况下远程控制 设置kill软件中的端口.密码.上线列表 2.在软件的Bin\Plugins目录下找到Consys21.dll复制到/phpstudy/www目录下留作生成软件 3 ...

  3. 每天一点点之 taro 框架 - 生命周期 & state

    注意:从vue过来的小朋友要注意,taro直接赋值时不会更新组件的,同react一致更新数据必须调用setState方法,例如:this.setState({name:'张三'}) 1.render函 ...

  4. vnpy交易学习接口(2)

    #来源于github下载vnpy版本  20180413 11.多投资标的情况下,该如何修改? 10.stop和limit报单有什么区别呢? 在交易时用得最多的是二类定单,第一类是市价单(Market ...

  5. EUI库 - 快速入口之项目配置

      egretProperties.json exmlRoot  指定exml文件存放根目录,该路径必须为相对路径,目录内只能有exml文件 themes    主题文件数组,配置所有主题文件路径,该 ...

  6. C#里的async和await的使用

    1. await指令调起线程执行异步方法和方法内后面的代码 2. await指令会阻塞当前方法后面的代码,但是不会阻塞外部调用 3. await必须搭配async使用,而async不一定需要有awai ...

  7. POJ 2014:Flow Layout 模拟水题

    Flow Layout Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 3091   Accepted: 2148 Descr ...

  8. CNN:转置卷积输出分辨率计算

    上一篇介绍了卷积的输出分辨率计算,现在这一篇就来写下转置卷积的分辨率计算.转置卷积(Transposed convolution),转置卷积也有叫反卷积(deconvolution)或者fractio ...

  9. 云平台发展前沿报告 微软云平台——Windows Azure

    微软云平台——Windows Azure Windows Azure 是微软研发的公有云计算平台.该平台可供企业在互联网上运行应用,并可进行扩展.通过Windows Azure,企业能够在多个数据中心 ...

  10. Codeforces 997A Convert to Ones(思维)

    https://codeforces.com/problemset/problem/997/A 题目大意: 给定一串0-1序列,定义两种操作: 操作一:选取一连续串倒置. 操作二:选取一连续串把进行0 ...