一维向量旋转算法 编程珠玑 第二章

看了编程珠玑第二章,这里面讲了三道题目,这里说一下第二题,一维向量旋转算法。

题目:将一个n元一维向量(例数组)向左旋转i个位置。

解决方法:书上讲解了5种方法,自己只想起来2种最简单方法(下面讲的前两种)。

1.原始方法。

  从左向右依次移动一位,对所有数据平移;这样循环i次,算法最坏时间复杂度达n^2.耗时不推荐。

2.空间换时间。

  顾名思义,申请一个i长度的空间,把前i半部分放到申请空间中,再把后面的所有数据向左移动i个位置,最后把申请的空间中的数据放到后半部分。浪费空间,不推荐。

3.杂技算法(编程珠玑叫的,另叫求模置换法)

  我们知道第一种方法,每次向左旋转一个位置(其时间正比于n),总共需要旋转i次。这个方案会消耗过多的运行时间。而求模置换的方法则是尽量让每个数一次移动到位。总体的思想是:以i为除数对n求模,将向量遍历完并一次移动到位。

  另编程珠玑讲解:移动x[0]到临时变量t,然后移动x[i]到x[0],x[2i]到x[i],依次类推,直到取到x[0](其中下标都对长度n取模);然后依次对x[1]...x[i-1]执行上面操作。

  此算法技巧性比较强,一般不大好想,代码稍微复杂,也不推荐。

  另书上有代码参考,c++形式如下:

 1 //求公约数的代码,欧几里得算法
 2 unsigned int Gcd(unsigned int a, unsigned int b)
 3 {
 4     unsigned int temp;
 5     while (b != 0)
 6     {
 7         temp = a % b;
 8         a = b;
 9         b = temp;
10     }
11
12     return a;
13 }
14 //对数组array[n]向左旋转rotdisk个位置
15 void zcxShift(int array[], int n, int rotdist)
16 {
17     unsigned int gcd = Gcd(n, rotdist);
18
19     for (int i = 0; i < gcd; i ++)
20     {
21         int temp = array[i];
22         int j = i;
23         int k;
24         while(1)
25         {
26             int k = j +  rotdist;
27             if (k >= n)
28             {
29                 k -= n;
30             }
31
32             if (k == i)
33             {
34                 break;
35             }
36
37             array[j] = array[k];
38             j = k;
39         }
40         array[j] = temp;
41     }
42
43 }

4.分段递归交换算法

  书上介绍:旋转向量x其实就是交换向量ab的两段,得到ba(a代表x中的前i个元素)。假设a比b短,将b分为b1和b2两段,使b2有跟a相同的长度,然后交换a和b2,也就是ab1b2交换得到b2b1a,a的位置已经是最终的位置,现在的问题集中到交换b2b1这两段,又回到了原来的问题。不断递归下去,到b1和b2的长度长度相等交换即可。

  书后答案有参考代码,c++描述如下:

 1 //交换操作,如下所示
 2 //swap x[a .. a+offset-1] and x[b .. b+offset-1]
 3 void swap(int array[], int a, int b, int offset)
 4 {
 5     int temp;
 6     for (int i = 0; i < offset; i++)
 7     {
 8         temp = array[a + i];
 9         array[a + i] = array[b + i];
10         array[b + i] = temp;
11     }
12 }
13
14 //交换主要代码
15 void swapShift(int *array, int n, int rotdist)
16 {
17     int p = rotdist;
18     int i = p;
19     int j = n - p;
20
21     while (i != j)
22     {
23         if (i > j)
24         {
25             swap(array, p - i, p, j);
26             i -=j;
27         }
28         else
29         {
30             swap(array, p - i, p + j - i, i);
31             j -= i;
32         }
33     }
34     swap(array, p - i, p, i);
35 }

5.翻手法(也叫求逆法)【推荐算法】

  思路很简单,把x向量分成ab两部分,a是前i个元素,b是后n-i个元素,首先对a求逆,然后对b求逆,然后对整体求逆得到ba。

  同样,c++代码如下:

 1 //求逆函数
 2 void reverse(int array[], int low, int high)
 3 {
 4     int temp = 0;
 5     for(int i = low; i <= (high + low) / 2; i++)
 6     {
 7         temp = array[i];
 8         array[i] = array[high - (i - low)];
 9         array[high - (i - low)] = temp;
10     }
11 }
12 //整个求逆法代码
13 void reverseShift(int *array, int n, int rotdist)
14 {
15     reverse(array, 0, rotdist - 1);
16     reverse(array, rotdist, n - 1);
17     reverse(array, 0, n - 1);
18 }

  算法5,简单明了,翻手算法代码非常简短,非常容易理解,而且针对字符串的求逆也不用自己写函数,在时间和空间上都很高效。再次推荐算法5。

另书后第五题,abc向量之翻转ac,思路同5,此处不再赘述!

一维向量旋转算法 编程珠玑 第二章,布布扣,bubuko.com

时间: 2024-11-08 19:20:41

一维向量旋转算法 编程珠玑 第二章的相关文章

编程珠玑第二章

编程珠玑第二章 A题 给定一个最多包含40亿个随机排列的32位整数的顺序文件,找出一个不在文件中一32位整数. 1.在文件中至少存在这样一个数? 2.如果有足够的内存,如何处理? 3.如果内存不足,仅可以用文件来进行处理,如何处理? 答案: 1.32位整数,包括-2146473648~~2146473647,约42亿个整数,而文件中只有40亿个,必然有整数少了. 2.如果采用位数思想来存放,则32位整数最多需要占用43亿个位.约512MB的内存空间. 可以采用前一章的位处理方法.然后判断每个in

[读书笔记]算法(Sedgewick著)·第二章.初级排序算法

本章开始学习排序算法 1.初级排序算法 先从选择排序和插入排序这两个简单的算法开始学习排序算法.选择排序就是依次找到当前数组中最小的元素,将其和第一个元素交换位置,直到整个数组有序. 1 public static void sort(Comparable a[]){ 2 int N = a.length; 3 for(int i = 0; i < N; i ++){ 4 int min = i; //最小元素索引 5 for(int j = i + 1; j < N; j++){ 6 if(

集体智慧编程_第二章(提供推荐)_1

前言:最近正在拜读Toby Segaran先生写的集体智慧编程,首先感谢Toby Segaran先生将知识以书本的方式传播给大家,同时也感谢莫映和王开福先生对此书的翻译,谢谢各位的不辞辛苦.首先在写随笔之前,跟各位分享一下我的编程环境:win7系统,python版本是2.7.10,开发环境我选择的是pycharm程序.本书的第一章为集体智慧导言,主要介绍的何为集体智慧和机器学习的相关概念和其局限性,以及与机器学习相关的例子和应用场景.下面开始机器学习第二章--提供推荐的相关内容. 本章主要内容:

算法导论_第二章(1)

年前的时候去逛书店,久仰算法导论这本书的大名看见后也就买了下来.回家看了一段时间,发现看书的进度真的是极慢,书里的课后题很多,那些不会的问题也是通过网上搜别人的答案才得以解决的.所以,我就想把我看这本书的心得连带课后的解答分享给大家.同时也是给我坚持把算法导论这本书看完的一个动力 ^_^ 因为本书的第一章相当于一个导论就直接跳过了,那么,从第二章开始! 第二章主要介绍了插入排序和归并排序: 所谓的插入排序就像是一局扑克刚开始时的摸牌阶段,你对手中的扑克所做的整理排序一样.开始时,我们的左手为空并

java编程思想 第二章

这篇时间较之前篇章时间靠后,是由于,某一天晚上看完Java编程思想文献之后来不及做笔记了. 以下笔记基本为转载,不是原创 第二章   一切都是对象 目录: 2.1 用引用操纵对象 2.2 必须由你创建所有对象 2.3 永远不需要销毁对象 2.4 创建新的数据类型:类 2.5 方法.参数和返回值 2.6 构建一个Java程序 2.7 你的第一个Java程序 2.8 注释和嵌入式文档 2.9 编码风格 2.1 用引用操纵对象 一切都看作对象,操纵的标识符实际上是对象的一个“引用”,遥控器(引用)操纵

[书籍翻译] 《JavaScript并发编程》 第二章 JavaScript运行模型

本文是我翻译<JavaScript Concurrency>书籍的第二章 JavaScript运行模型,该书主要以Promises.Generator.Web workers等技术来讲解JavaScript并发编程方面的实践. 完整书籍翻译地址:https://github.com/yzsunlei/javascript_concurrency_translation .由于能力有限,肯定存在翻译不清楚甚至翻译错误的地方,欢迎朋友们提issue指出,感谢. 本书第一章我们探讨了JavaScri

集体智慧编程:第二章,推荐算法

有一个网站,允许用户对她看过的电影打分.一个可能的结果是: 用户1:{电影1=5:电影2=3:电影3=4} 用户2: 用户3: 省略其他用户. 现在网站向一个用户Jack推荐电影,最直接的方式是,找出与Jack品味最接近的人,也就需要把所有用户按照他们与jack的相似度排序. 怎么计算相似度呢? 第一种方式是向量距离,也就是常用的(x1-x2)^2+(y1-y2)^2开根号. 第二种方式是pearson相关系数,利用的是斜率,比如jack喜欢打高分(A:5,B:4)tom喜欢打低分(A:3,B:

对一千万条数据进行排序---编程珠玑第二版 第一章

本书第一章提出了一个看似简单的问题,有最多1000万条不同的整型数据存在于硬盘的文件中,如何在1M内存的情况下对其进行尽可能快的排序. 每个数字用4byte,1M即可存储250 000个数据,显然,只要每次对250 000个数据排序,写入到文件中即可,重复40次. 那么如何选出每次遍历的二十五万条数据呢?有如下两个策略: 1.对一千万条数据遍历40次,第i次遍历时,判断数是否属于[i*250000,i*250000+249999),如果是,则读入内存,当第i次遍历完成时,内 存中有了二十五万条数

[算法竞赛入门]第二章_循环结构程序设计

第2章 循环结构程序设计 [学习内容相关章节] 2.1for循环 2.2循环结构程序设计 2.3文件操作 2.4小结与习题 [学习目标] (1)掌握for循环的使用方法: (2)掌握while循环的使用方法: (3)学会使用计算器和累加器: (4)学会用输出中间结果的方法调试: (5)学会用计时函数测试程序效率: (6)学会用重定向的方式读写文件: (7)学会fopen的方式读写文件: (8)了解算法竞赛对文件读写方式和命名的严格性: (9)记住变量在赋值之前的值是不确定的: (10)学会使用条