n维向量旋转(循环移位)——学习《编程珠玑》
2016-05-12 23:20
302 查看
问题:
将一个n元一维向量向左旋转i个位置。例如,当n=8且i=3时,向量abcdefgh旋转为defghabc。
简单的代码使用一个n元的中间向量在n步内完成该工作。
你能否仅使用数十个额外字节的存储空间,在正比于n的时间内完成向量的旋转?
解法:
将x的前i个元素复制到一个临时数组中,然后将剩下的n-i个元素向左移动i个位置,最后将最初的i个元素从临时数组中复制到x中余下的位置。——使用i个额外位置产生过大的存储空间消耗;
定义一个函数将x向左旋转一个位置,时间正比于n,然后调用该函数i次。——产生过多的运行时间消耗;
精巧算法:移动x[0]到临时变量t,然后移动x[i]至x[0],x[2i]至x[i],以此类推(将x中的所有下标对n取模),直至返回到取x[0]中的元素,此时改为从t取值然后终止过程。如果该过程没有移动全部元素,就从x[1]开始再次进行移动,直到所有元素都已移动位置。——不需要大量存储空间,时间复杂度为n;
二分法:旋转向量x实际上就是交换向量ab的两段,获得ba。这里a代表x的前i个元素。假如a比b短,将b分为b_l和b_r两段,使得b_r具有与a相同的长度。交换a和b_r,也就是将ab_lb_r转换成b_rb_la。序列a此时已处于最终位置,现在问题变为交换b_rb_l两部分,该问题与原问题具有相同的形式,因此可以递归求解。
翻转法:假定我们拥有一个函数可以将数组中特定部分求逆。从ab开始,首先对a求逆,得到a^rb,然后对b求逆,得到a^rb^r。最后整体求逆得到(a^rb^r)^r,此时正好是ba。于是我们得到以下用于旋转的代码:
将一个n元一维向量向左旋转i个位置。例如,当n=8且i=3时,向量abcdefgh旋转为defghabc。
简单的代码使用一个n元的中间向量在n步内完成该工作。
你能否仅使用数十个额外字节的存储空间,在正比于n的时间内完成向量的旋转?
解法:
将x的前i个元素复制到一个临时数组中,然后将剩下的n-i个元素向左移动i个位置,最后将最初的i个元素从临时数组中复制到x中余下的位置。——使用i个额外位置产生过大的存储空间消耗;
定义一个函数将x向左旋转一个位置,时间正比于n,然后调用该函数i次。——产生过多的运行时间消耗;
精巧算法:移动x[0]到临时变量t,然后移动x[i]至x[0],x[2i]至x[i],以此类推(将x中的所有下标对n取模),直至返回到取x[0]中的元素,此时改为从t取值然后终止过程。如果该过程没有移动全部元素,就从x[1]开始再次进行移动,直到所有元素都已移动位置。——不需要大量存储空间,时间复杂度为n;
二分法:旋转向量x实际上就是交换向量ab的两段,获得ba。这里a代表x的前i个元素。假如a比b短,将b分为b_l和b_r两段,使得b_r具有与a相同的长度。交换a和b_r,也就是将ab_lb_r转换成b_rb_la。序列a此时已处于最终位置,现在问题变为交换b_rb_l两部分,该问题与原问题具有相同的形式,因此可以递归求解。
翻转法:假定我们拥有一个函数可以将数组中特定部分求逆。从ab开始,首先对a求逆,得到a^rb,然后对b求逆,得到a^rb^r。最后整体求逆得到(a^rb^r)^r,此时正好是ba。于是我们得到以下用于旋转的代码:
reverse(0, i - 1) reverse(i, n - 1) reverse(0, n - 1)
相关文章推荐
- 使用Java显示图片
- 第一个Java程序,简单的打开图片并显示在面板上
- Spring JMS---三种消息监听器
- JPA规范介绍及实例(Java数据持久化解决方案)
- Java for-each循环
- java中带继承类的加载顺序详解及实战
- spring基础知识汇总及常见面试题目总结
- python之cpu性能检测脚本
- 值得推荐的C/C++框架和库
- 批量更改文件的扩展名
- Java上传下载excel、解析Excel、生成Excel的问题
- 【Qt】标准颜色对话框类
- 基于Servlet+JSP+JavaBean开发模式的用户登录注册
- Java 版 (精华区)--Frame和Panel的区别【转载
- 两个java数组删除相同元素
- 第7周 C语言程序设计(新2版) 练习1-19 颠倒字符串中的字符
- github上的QT源码,必要的时候还是应该看一下,仅凭猜测很容易出错
- HDU 1042 N! (大数阶乘,紫书上的方法超时!!还是Java大法好!!)
- asp:net button控件
- PHPStorm + Homestead + Xdebug + Chrome Xdebug Helper 调试配置