第 2 章 第 3 题 数组旋转问题 杂技算法实现

问题分析

  输入:目标数组,旋转位数。

  处理:将目标数组旋转指定的位数。

  约束:无

解答思路

  见P13页底部,一种类似杂技演员表演的移动元素的技巧。

  PS:控制每次" 杂技 "的结束是实现这个算法的关键所在,也是回答本题的第二问,请参考下面代码的注释部分。

代码实现

 1 #include <iostream>
 2 
 3 using namespace std;
 4 
 5 // 数组旋转函数
 6 void rotate(int *array, int n, int r);
 7 // 最大公约数函数
 8 int gcd( int a, int b);
 9 
10 int main(void)
11 {
12     // 建立并初始化,输出测试数组。
13     int array[10];
14     int n=10;
15     for (int i=0; i<10; i++) {
16         array[i] = i+1;
17     }
18     cout << "目标数组:" << endl;
19     for (int i=0; i<10; i++) {
20         cout << array[i] << " ";
21     }
22     cout << endl;
23 
24     // 获取旋转位数
25     int r;
26     cout << "旋转位数:";
27     cin >> r;
28 
29     // 处理旋转位数
30     if (r<0) {
31         cout << "非法的旋转位数" << endl;
32         return 0;
33     }
34     else
35         r %= n;
36 
37     // 调用数组旋转函数
38     rotate(array, n, r);
39 
40     // 打印旋转结果
41     cout << endl << "旋转后的数组:" << endl;
42     for (int i=0; i<10; i++) {
43         cout << array[i] << " ";
44     }
45     cout << endl;
46 
47     return 0;
48 }
49     
50 void rotate(int *array, int n, int r) {
51     // 数组长度 n 和旋转位数 r 的最大公约数就是需要置换的轮次数
52     // 或者理解为表演杂技的" 次数 "
53     int d = gcd(r, n);
54 
55     for (int i=0; i<d; i++) {
56         // t 暂存旋转操作的首元素
57         int t = array[i];
58 
59         // 每个轮次的操作
60         int j = i;
61         while ( (j+r)%n != i ) {
62             array[j] = array[(j+r)%n];
63             j = (j+r)%n;
64         }
65 
66         // 将 t 中暂存元素放回数组
67         array[j] = t;
68     }
69 }
70 
71 int gcd( int a, int b ){
72     return b==0 ? a : gcd(b, a%b);
73 }

运行测试

  

小结

  这个算法很不错,不需要特别的空间,消耗的时间也不多。

  但需要记住 n 和 r 的最大公约数的求法

posted on 2014-04-01 17:33  空山悟  阅读(278)  评论(0编辑  收藏  举报

导航