向量循环移位之高效实现

问题:n个元素的向量V循环移位(以左移为例)i个位置,例如12345循环移动2个位置得到34512.

问题本身非常简单,以至于我们一看到问题就能想到对应的解决策略:申请i个字节的动态存储,将向量区间[0,i-1]的i个元素存储至临时存储器,之后将[i,n]的n-i+1个元素向左移动i个位置,并将临时存储器中的i个元素写回原向量区间中[n-i+1,n]。但如果我们强加一些限制:在现有可申请内存的总量k << i以及所要求的时间复杂度为O(n)的情况下如何实现循环移位?问题的复杂度似乎就上了一个量级。而之所以写这篇文章,很大程度上是因为接下来要介绍的三种方法带来了对问题本质更深入的思考。

方法一(姑且称之为求模法):借助一个临时变量temp,temp ← V[0],V[0] ← V[i%n],V[i%n] ← V[(2i)%n]…直到(ki)%n =0时,此时所要完成的操作即为V[((k-1)i)%n] ← V[0],而由于变量V[0]的值在被V[i%n]覆盖之前已存入temp,取而代之的操作即为:V[((k-1)i)%n] ← temp。图解表示为(图示的移位个数为i=3):

整个操作过程借助一个临时变量,经过n次左右的操作即完成整个移位过程,时间复杂度满足O(n)。事实上,向量中所有的元素都进行了移位操作,因此如果当完成V[((k-1)i)%n] ← temp操作时,仍有元素未完成移动,此时从V[1]开始再次进行移动。因为如果没有移动全部的元素,则说明最初的i个元素将分为m(m>1)个等价类,所以从V[1]开始再次移动是可行的,这归功于等价类的性质:任何求模等价类聚集中每个集合中的每个元素间隔的长度相等。所以若0和1同属一个等价类,则该等价类必然包含所有i个元素。

上述过程的伪码表示为:

/*LOOPSHIFT(V,i)*/
cnt←0
j←-1
while cnt≠length[V]
  do j←j+1
     temp←V[j]
     k←i+j
     while k%n≠j
       do V[(k-i)%n]←V[k%n]
          k←k+i
          cnt←cnt+1
     V[(k-i)%n]←temp
     cnt←cnt+1

在继续深入考虑之前先思考以下两种情况:①在13个元素中循环移动5个元素(12/5) ②在14个元素中移动4个元素(14/4),其中⌈⌉表示上取整,⌊⌋表示下取整。

1)在13/5这种情况中,由于(⌈12/5⌉)×5-12=3,每次在5个元素中以2进行循环迭代,在[0,4]这5个元素中的迭代次序为(不考虑向量中的其他元素):0→3→1(6%5)→4(9%5)→2(12%5)→0(15%5),因此最终通过上述代码的一次内层循环即可完成整个移位操作。

2)在14/4这种情况中,由于(⌈14/4⌉)×4-14=2,每次在4个元素中也以2进行循环迭代,在[0,3]这5个元素中的迭代次序为:0→2→0(4%2)→1(退出内层循环,简单从下标为1的元素重新开始移动)→3→1(5%2),因此最后在外层执行两次迭代才最终完成整个移位操作。

通过这两个例子可以发现外层的迭代次数(即等价类的个数)最终和整个向量的长度以及所要移位的个数有关,具体的关系为:cnt = gcd(n,i)  其中n=length[A],cnt为外层迭代的次数。

由于任何求模等价类聚集中每个集合中的元素间隔的长度相等(由上可知,即实际过程中未进行模运算之前的值),据此证明过程如下:

因为length[V]=n且移位个数为i,因此必然存在大于等于n且被i整除的数k=⌈n/i⌉×i

由n= α×gcd(n,i)且i=β×gcd(n,i),k=⌈n/i⌉×β×gcd(n,i)

因此在i个元素上每次移位的个数为iter=k-n=(⌈n/i⌉×β-α)×gcd(n,i),即iter能被gcd(n,i)整除

由于对元素求模各等价类的个数即为等价类中每个元素的间隔长度,因此实际在i个元素中进行iter个移位所得的等价类即为:

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值