mirror of
https://github.com/heqin-zhu/algorithm.git
synced 2024-03-22 13:30:46 +08:00
113 lines
3.4 KiB
Python
113 lines
3.4 KiB
Python
|
''' mbinary
|
|||
|
#########################################################################
|
|||
|
# File : rotate.py
|
|||
|
# Author: mbinary
|
|||
|
# Mail: zhuheqin1@gmail.com
|
|||
|
# Blog: https://mbinary.xyz
|
|||
|
# Github: https://github.com/mbinary
|
|||
|
# Created Time: 2018-05-19 21:54
|
|||
|
# Description: three methods of rotating a list
|
|||
|
|
|||
|
1. 利用 ba=(br)^T(ar)^T=(arbr)^T,通过三次反转字符串: 即首先对序列前部分逆序,再对序列后部分逆序,再对整个序列全部逆序
|
|||
|
|
|||
|
2. 分组交换(尽可能使数组的前面连续几个数为所要结果):a长度大于b,将 ab 分成 a0a1b,交换 a0 和 b,得 ba1a0,只需再交换 a1和 a0。若 a 长度小于 b,将 ab 分成 ab0b1,交换 a 和 b0,得 b0ab1,只需再交换 a 和b0。通过不断将数组划分,和交换,直到不能再划分为止。分组过程与求最大公约数很相似。
|
|||
|
|
|||
|
3.所有序号为 (j+i*m) % n (j 表示每个循环链起始位置,i 为计数变量,m 表示左旋转位数,n 表示字符串长度),会构成一个循环链(共有 gcd(n,m)个,gcd 为 n、m 的最大公约数),每个循环链上的元素只要移动一个位置即可,最后整个过程总共交换了 n 次(每一次循环链,是交换 n/gcd(n,m)次,总共 gcd(n,m)个循环链。所以,总共交换 n 次)。
|
|||
|
|
|||
|
#########################################################################
|
|||
|
'''
|
|||
|
|
|||
|
def rotate(s,k,right=False):
|
|||
|
def reverse(a,b):
|
|||
|
while a<b:
|
|||
|
s[a],s[b]=s[b],s[a]
|
|||
|
a+=1
|
|||
|
b-=1
|
|||
|
n=len(s)
|
|||
|
k = k%n if not right else n-k%n
|
|||
|
reverse(0,k-1)
|
|||
|
reverse(k,n-1)
|
|||
|
reverse(0,n-1)
|
|||
|
return s
|
|||
|
|
|||
|
|
|||
|
|
|||
|
def rotate2(s,k,right=False):
|
|||
|
def swap(a,b,c):
|
|||
|
for i in range(c):
|
|||
|
s[a+i],s[b+i] = s[b+i],s[a+i]
|
|||
|
def _rot(pl,pr):
|
|||
|
''' swap s[pl,pr) , s[pr:]'''
|
|||
|
if pr==n:return
|
|||
|
if pr-pl<=n-pr:
|
|||
|
swap(pl,pr,pr-pl)
|
|||
|
_rot(pr,2*pr-pl)
|
|||
|
else:
|
|||
|
swap(pl,pr,n-pr)
|
|||
|
_rot(n-pr+pl,pr)
|
|||
|
n=len(s)
|
|||
|
k = k%n if not right else n-k%n
|
|||
|
_rot(0,k)
|
|||
|
return s
|
|||
|
|
|||
|
|
|||
|
|
|||
|
def rotate3(s,k,right=False):
|
|||
|
def gcd(a,b):
|
|||
|
if b==0:return a
|
|||
|
return gcd(b,a%b)
|
|||
|
|
|||
|
n=len(s)
|
|||
|
k = k%n if not right else n-k%n
|
|||
|
r=gcd(n,k)
|
|||
|
for i in range(r):
|
|||
|
tmp = s[i]
|
|||
|
j = (i+k)%n
|
|||
|
while j!=i:
|
|||
|
s[j-k] = s[j]
|
|||
|
j = (j+k)%n
|
|||
|
s[(j-k+n)%n] = tmp
|
|||
|
return s
|
|||
|
|
|||
|
|
|||
|
def test():
|
|||
|
def f(func,*args,right=False):
|
|||
|
print(' '.join(['testing:',func.__name__,str(args),'right=',str(right)]))
|
|||
|
rst = func(*args,right=right)
|
|||
|
print('result',rst)
|
|||
|
print()
|
|||
|
return f
|
|||
|
|
|||
|
|
|||
|
if __name__=='__main__':
|
|||
|
s=[i for i in range(10)]
|
|||
|
tester= test()
|
|||
|
tester(rotate,s,4,right=True)
|
|||
|
tester(rotate,s,4)
|
|||
|
tester(rotate2,s,2,right=True)
|
|||
|
tester(rotate2,s,2)
|
|||
|
tester(rotate3,s,132,right=True)
|
|||
|
tester(rotate3,s,132)
|
|||
|
|
|||
|
|
|||
|
'''
|
|||
|
testing: rotate ([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 4) right= True
|
|||
|
result [6, 7, 8, 9, 0, 1, 2, 3, 4, 5]
|
|||
|
|
|||
|
testing: rotate ([6, 7, 8, 9, 0, 1, 2, 3, 4, 5], 4) right= False
|
|||
|
result [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
|||
|
|
|||
|
testing: rotate2 ([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 2) right= True
|
|||
|
result [8, 9, 0, 1, 2, 3, 4, 5, 6, 7]
|
|||
|
|
|||
|
testing: rotate2 ([8, 9, 0, 1, 2, 3, 4, 5, 6, 7], 2) right= False
|
|||
|
result [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
|||
|
|
|||
|
testing: rotate3 ([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 132) right= True
|
|||
|
result [8, 9, 0, 1, 2, 3, 4, 5, 6, 7]
|
|||
|
|
|||
|
testing: rotate3 ([8, 9, 0, 1, 2, 3, 4, 5, 6, 7], 132) right= False
|
|||
|
result [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
|||
|
|
|||
|
'''
|