mirror of
https://github.com/heqin-zhu/algorithm.git
synced 2024-03-22 13:30:46 +08:00
116 lines
3.6 KiB
Python
116 lines
3.6 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]
|
||
|
||
'''
|