B题是这样子的:

  将一个n元一维向量向左旋转(即循环移位)i个位置。例如,当n=8且i=3时,向量abcdefgh旋转为defghabc。简单的代码使用一个n元的中间向量在n步内完成该工作。你能否仅使用数十个额外字节的存储空间,在正比于n的时间内完成向量的旋转?

  以下题目的解答部分参考自一博文及该书参考答案。

  分析: 

  “abcdefgh”严格来说并不是一个字符串,因为'\0'是不会移动的。为了叙述方便,可以把它认为是字符串,只是不对'\0'进行操作罢了。

  如果不考虑时间要求为O(n),那么可以每次整体左移一位,一共移动i次。只使用O(1)的空间的条件下,一共要进行元素交换O(n*i)次;

  如果不考虑空间要求为O(1),那么可以把前i个存入临时数组,剩下的左移i位,再把临时数组里的内容放入后i个位置中。

  很可惜,由于两个限制条件,以上两种思路都不满足要求。

  1. 法一:"杂技"代码

  为了满足O(1)空间的限制,延续第一个思路,如果每次直接把原向量的一个元素移动到目标向量中它的应该出现新位置上就行了。先把array[0]保存起来,然后把array[i]移动到array[0]上,array[2i]移到array[i]上,直至返回取原先的array[0]。但这需要解决的问题是,如何保证所有元素都被移动过了?数学上的结论是,依次以array[0],...,array[gcd(i,n)-1]为首元进行循环即可,其中gcd(a,b)是a与b的最大公约数。

 void cyclicShift(char * in, int len, int shift)
{
assert(len >= );
assert(shift >= );
if (shift == || shift == len)
{
return;
}
if (shift > len)
{
shift = shift % len;
} int k, j;
char temp;
int times = gcd(len, shift);
for (int i = ; i < times; i++)
{
j = i;
temp = in[i];
while (true)
{
k = (j + shift) % len;
if (k == i) break;
in[j] = in[k];
j = k;
}
in[j] = temp;
}
} int gcd(int a, int b)
{
assert(a > && b > ); // Method1
// int r;
//while (b > 0)
//{
// r = a%b;
// a = b;
// b = r;
//} // Method2
while (a != b)
{
if (a > b)
a -= b;
else
b -= a;
} return a;
}

  正如“杂技”一词所暗示的一样,这个算法就像在玩杂耍球,你要让它们中的每一个都在合适的位置上,这些球,除了手中有一个,其它几个都在空中。如果不熟悉,很容易手忙脚乱,把球掉的满地都是。

  2. 法二:求逆(推荐)

  把原向量分为两部分a和b,分别对a、b求逆得到arbr,再对整体求逆便获得了ba!即(arbr)r = ba。代码如下:

 void cyclicShift3(char * in, int len, int shift)
{
assert(len >= );
assert(shift >= );
if (shift == || shift == len)
{
return;
}
if (shift > len)
{
shift = shift % len;
} reverse(in, , shift - );
reverse(in, shift, len - );
reverse(in, , len - );
} void reverse(char * in, int first, int last)
{
assert(first >= );
assert(last >= );
assert(first <= last); char temp;
while (first < last)
{
temp = in[first];
in[first] = in[last];
in[last] = temp;
first++;
last--;
}
}

  这种方法无疑既高效,也难以在编写时出错。有人曾主张把这个求逆的左旋方法当做一种常识。

  来看看这种思想的应用吧:

  扩展:(google面试题)用线性时间和常数附加空间将一篇文章的所有单词倒序。

  举个例子:This is a paragraph for test

  处理后: test for paragraph a is This

  如果使用求逆的方式,先把全文整体求逆,再根据空格对每个单词内部求逆,是不是很简单?另外淘宝今年的实习生笔试有道题是类似的,处理的对象规模比这个扩展中的“一篇文章”小不少,当然解法是基本一样的,只不过分隔符不是空格而已,这里就不重述了。

“《编程珠玑》(第2版)第2章”:B题(向量旋转)的更多相关文章

  1. 《编程珠玑(第2版)》【PDF】下载

    <编程珠玑(第2版)>[PDF]下载链接: https://u253469.pipipan.com/fs/253469-230382225 内容简介 书的内容围绕程序设计人员面对的一系列实 ...

  2. java编程思想第四版第十一章习题

    第一题 package net.mindview.holding.test1; import java.util.ArrayList; import java.util.List; /** * 沙鼠 ...

  3. java编程思想第四版第六章总结

    1. 代码重构 为什么f要代码重构 第一次代码不一定是完美的, 总会发现更优雅的写法. 代码重构需要考虑的问题 类库的修改不会破坏客户端程序员的代码. 源程序方便扩展和优化 2. 包 创建一个独一无二 ...

  4. Java编程思想第四版*第七章*个人练习

    欢迎加群:239063848 成团的笔记:该组仅用于技术共享和交流,问题和答案公布 潘基聊天.禁止广告.禁止招聘-- 练习1:(2)创建一个简单的类.第二个类中,将一个引用定义为第一个类的对象.运用惰 ...

  5. java编程思想第四版第五章习题

    创建一个类, 它包含一个未初始化的String引用.验证该引用被Java初始化成了null package net.mindview.initialization; public class Test ...

  6. java编程思想第四版第六章习题

    (略) (略) 创建两个包:debug和debugoff,他们都包含一个相同的类,该类有一个debug()方法,第一个版本显示发送给控制台的String参数,而第二版本什么也不做,使用静态import ...

  7. java编程思想 第四版 第六章 个人练习

    欢迎加群:239063848 进群须知:本群仅用于技术分享与交流.问题公布与解答 禁止闲聊.非诚勿扰 练习1:(1)在某个包中创建一个类,在这个类所处的包的外部创建该类的一个实例. import mi ...

  8. java编程思想第四版第9章

    练习3: public class MainTest { public static void main(String args[]){ Bcycle b=new Bcycle(); b.print( ...

  9. Java编程思想第四版 *第五章 个人练习

    练习3:(1)创建一个带默认构造器(即无參构造器)的类.在构造器中打印一条消息.为这个类创建一个对象.P116 public class Test{ public Test(){ System.out ...

  10. java编程思想第四版第十三章字符串 总结

    1. String和StringBulider的使用 通过书中介绍, 我们得知如下结论: 当使用+连接符将字符串进行拼接的时候, 编译器会进行自动优化为使用StringBuilder连接字符串. 当在 ...

随机推荐

  1. Java异常处理-----Throwable类

    Throwable类 1.toString() 输出该异常的类名. 2.getMessage() 输出异常的信息,需要通过构造方法传入异常信息(例如病态信息). 3.printStackTrace() ...

  2. RxJava操作符(05-结合操作)

    转载请标明出处: http://blog.csdn.net/xmxkf/article/details/51656736 本文出自:[openXu的博客] 目录: CombineLatest Join ...

  3. RxJava(一) create操作符的用法和源码分析

    欢迎转载,转载请标明出处: http://blog.csdn.net/johnny901114/article/details/51524470 本文出自:[余志强的博客] 1 create操作符的基 ...

  4. [django] 利用多线程增加异步任务

    看到django异步大家的反应应该是celery这种消息队列组件,现在用的最多的最推荐的也是这种方式.然而我这需求就是请求来了,执行一个小程序,但是又不能确定这个小程序啥时候执行完,响应又要及时,丢给 ...

  5. 剑指Offer——搜狐畅游笔试题+知识点总结

    剑指Offer--搜狐畅游笔试题+知识点总结 情景回顾 时间:2016.9.24 10:00-12:00 地点:山东省网络环境智能计算技术重点实验室 事件:搜狐畅游笔试   注意事项:要有大局观,该舍 ...

  6. Intellij IDEA 插件开发之自建插件仓库

    Intellij IDEA 有一个自己的官方的插件仓库,但是当我们的开发的 Intellij IDEA 的插件不能够对外公开时,我们就需要搭建自己的 Intellij IDEA 的插件仓库.前不久我们 ...

  7. 利用CocoaHTTPServer实现wifi局域网传输文件到iphone

    背景 近日在做一个代码阅读器,其中涉及到代码文件的上传,之前看到过许多app支持局域网传文件,因此就通过查询和研究实现了此功能,我是用的框架是CocoaHTTPServer. 原理 CocoaHTTP ...

  8. Spark调度模式-FIFO和FAIR

    Spark中的调度模式主要有两种:FIFO和FAIR.默认情况下Spark的调度模式是FIFO(先进先出),谁先提交谁先执行,后面的任务需要等待前面的任务执行.而FAIR(公平调度)模式支持在调度池中 ...

  9. 【一天一道LeetCode】#258. Add Digits

    一天一道LeetCode 本系列文章已全部上传至我的github,地址:ZeeCoder's Github 欢迎大家关注我的新浪微博,我的新浪微博 欢迎转载,转载请注明出处 (一)题目 Given a ...

  10. android studio——Failed to set up SDK

    最近使用android studio ,在IDE里面使用Gradle构建的时候,一直出现构建失败,失败信息显示Failed to set up SDK.然后 提示无法找到andriod-14平台,我更 ...