n维向量旋转(循环移位)——学习《编程珠玑》

问题:

将一个n元一维向量向左旋转i个位置。例如,当n=8且i=3时,向量abcdefgh旋转为defghabc。

简单的代码使用一个n元的中间向量在n步内完成该工作。

你能否仅使用数十个额外字节的存储空间,在正比于n的时间内完成向量的旋转?

解法:

  1. 将x的前i个元素复制到一个临时数组中,然后将剩下的n-i个元素向左移动i个位置,最后将最初的i个元素从临时数组中复制到x中余下的位置。——使用i个额外位置产生过大的存储空间消耗;
  2. 定义一个函数将x向左旋转一个位置,时间正比于n,然后调用该函数i次。——产生过多的运行时间消耗;
  3. 精巧算法:移动x[0]到临时变量t,然后移动x[i]至x[0],x[2i]至x[i],以此类推(将x中的所有下标对n取模),直至返回到取x[0]中的元素,此时改为从t取值然后终止过程。如果该过程没有移动全部元素,就从x[1]开始再次进行移动,直到所有元素都已移动位置。——不需要大量存储空间,时间复杂度为n;
  4. 二分法:旋转向量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两部分,该问题与原问题具有相同的形式,因此可以递归求解。
  5. 翻转法:假定我们拥有一个函数可以将数组中特定部分求逆。从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)
    
千里之行,始于足下~
原文地址:https://www.cnblogs.com/wm123/p/5487834.html