旋转数组

来源:互联网 发布:网络直播 yy 编辑:程序博客网 时间:2024/05/01 10:03

问题定义:

      给定一个数组data[]和一个数M,向右旋转M位,要求时间复杂度为O(n),空间复杂度为O(1),如,char data[]="abcde", M = 2,旋转以后data 应该为cdeab,如何高效的实现该功能?

这是一个非常经典的题目,第一次自己看到可能根本想不出来,也是09年计算机研究生入学考试的算法题,该题在《编程珠玑》和《编程之美》里都有讨论,写这篇文章的原因是今天发现了STL对该问题的一个高效算法。

1. 编程珠玑里的解法

不失一般性,我们假设数组有N个元素,旋转M位,且(N>M),那么可以这么考虑问题,数组前M位为a,数组后N-M位为b,则数组是ab,我们知道数学里有如下公式:

ba=(a'b')' (' 表示置逆)


这就是编程珠玑里的算法,先把前M个数置逆,再把后N-M个数置逆,然后置逆整个数组,就得到我们要的结果了。

2. STL使用的方法

STL的源代码如下:

template <class ForwardIterator>  void rotate ( ForwardIterator first, ForwardIterator middle,                ForwardIterator last ){  ForwardIterator next = middle;  while (first!=next)  {    swap (*first++,*next++);    if (next==last) next=middle;    else if (first == middle) middle=next;  }}


上面咋的一看,可能看不懂是什么意思,我们来分析一下,还是一样,假设数组有N个元素,旋转M位,且(N>M),我们首先考虑M < N-M的情况,我们可以把数组分成三部分,分别是ab1b2,然后算法执行一轮以后,就得到:b1ab2,剩下要做的事情就是交换ab2的顺序,且中点应该在ab2交接的地方,所以有middle=next,然后继续递归执行。另外一种情况恰好是M>N-M的情况,在此不在敖述。