首页 > 编程语言 > 详细

10-排序6 Sort with Swap(0, i) (25 分)

时间:2019-06-02 11:39:50      阅读:164      评论:0      收藏:0      [点我收藏+]

Given any permutation of the numbers {0, 1, 2,..., N1}, 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 (≤) followed by a permutation sequence of {0, 1, ..., N1}. 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

一、思路

(一)规律:

  1.N个数字排列整齐的条件是Position[X] == X

  2.N个数字的全排列(permutation)必定构成若干个闭环。

  3.Swap(0, X)就相当于Swap(Position[0], Position[X])

 

 

(二)说明

0.规律2

如样例:

 X     3 5 7 2 6 4 9 0 8 1

   Position 0 1 2 3 4 5 6 7 8 9    

   Position[7] = 0; Position[0] = 3; Position[3] = 2; Position[2] = 7; Position[7] = 0 …………

 

1.由规律2 && 规律3容易得到,针对0的元素交换只能在包含0的闭环中进行。

如: 对于7-0-3-2-7闭环中,无论怎么交换,最后情况

Position[7] = 7;

Position[0] = 0;

Position[3] = 3;

Position[2] = 2

 

2.所以如果排序序列中有多个环,就要让0进入不包含0的环,进入的方法也很简单:

Swap(Position[0], Postion[X]) where X is any member of any anther loop.

 

3.按照题意(4,0,2,1,3)交换顺序的提示,本题应该是贪心(greedy)算法的意思。

即每次Swap,把Position[0]对应的元素拉回原位。

如:

1.Position[0] = 3 

2.Position[3] = 2;

3.Swap( Position[0], Position[3] )

Outcome:

Position[0] = 2;

Position[3] = 3; /*correct position*/

 

4. 按照贪心算法,可以简化步骤2,因为每次包含0的环在进行若干次Swap后所有元素均有序,

所以剩下的不包含0的环的元素有一个共同特点——即Position[X] !=X

 

 

(三)步骤

步骤一、

根据说明3复位含0的闭环中的所有元素

步骤二、

查找仍在错误位置的X,交换(0,X);若找不到则退出循环

步骤三、

Swap(0,X),回步骤一

 

 

 

二、具体实现

(一)数据结构的选择

1.数组

技术分享图片
 1 #include <cstdio>
 2 #include <algorithm>
 3 
 4 using namespace std;
 5 const int MAXN = 1e5 + 1;
 6 
 7 int Position[MAXN];
 8 void ZeroSort(int N);
 9 
10 int main()
11 {
12     int N, tmp;
13     scanf("%d", &N);
14     
15     for (int i=0; i<N; i++) {
16         scanf("%d", &tmp);
17         Position[tmp] = i;
18     }
19     
20     
21     
22     ZeroSort( N );
23     
24     
25     return 0;
26     
27 }
28 
29 void ZeroSort(int N)
30 {
31     int P, PreZeroPos, cnt;
32     cnt = 0;
33     
34     while (1) {
35         PreZeroPos = Position[0];
36         
37         if (Position[0] != 0) {
38             swap( Position[0], Position[Position[0] ] );
39         }
40         else {
41             for (P=0; P<N; P++) if(Position[P] != P) break;
42             swap( Position[0], Position[P] );
43         }
44         if (PreZeroPos == Position[0]) {
45             break;
46         }
47         cnt++;
48         }
49     
50     printf("%d\n", cnt);
51         
52 }
53    
V1

2.数组+std::set(内部实现是AVL树)

技术分享图片
 1 #include <cstdio>
 2 #include <algorithm>
 3 #include <set>
 4 using namespace std;
 5 const int MAXN = 1e5 + 1;
 6 
 7 int Position[MAXN];
 8 
 9 
10 
11 void ZeroSort(int N, set<int> St);
12 
13 
14 int main()
15 {
16     int N, tmp;
17     set<int> St;
18     
19     scanf("%d", &N);
20     
21     for (int i=0; i<N; i++) {
22         scanf("%d", &tmp);
23         Position[tmp] = i;
24         if (Position[i] != i and i!=0) {
25             St.insert(i);
26         }
27     }
28     
29     
30     
31     ZeroSort( N, St );
32     
33     return 0;
34     
35 }
36 
37 
38 
39 void ZeroSort(int N, set<int> St)
40 {
41     int PreZeroPos, cnt, X;
42     cnt = 0;
43     
44     //O(N)
45     while (St.size() != 0) {
46         PreZeroPos = Position[0];
47         
48         if (PreZeroPos != 0) {
49             swap( Position[0], Position[ PreZeroPos ] );
50             St.erase( St.find(PreZeroPos) );
51         }
52         
53         else {
54             X = *(St.begin());
55             swap( Position[0], Position[X] );
56         }
57         
58         cnt++;
59         
60         }
61     
62     printf("%d\n", cnt);
63         
64 }
65    
V2

(二)分析

Version1 超时

分析:

如何识别Position[X] != X,Version 1中扫描了整个数组,O(N)

外面的大循环显然也是O(N)的,因为最坏情况下S要Swap N-1 次;

总的复杂度O(N^2),N=1e5不可接受。

 

Version2 AC

分析:

1.步骤一、

复位X后删除MalPosSt中的元素,表示该元素已经复位。O(logN)

2.步骤二、

任选MalPosSt中元素,此处我选了*( MalPosSt.begin() )。 O(1)

3.步骤三、

O(1)

外面大循环O(N),总的复杂度为O(NlogN

 

10-排序6 Sort with Swap(0, i) (25 分)

原文:https://www.cnblogs.com/acoccus/p/10935774.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!