【发布时间】:2020-01-19 18:50:33
【问题描述】:
前提:我的问题不是 Cyclic rotation in Python 的重复。我不是在问如何解决问题或为什么我的解决方案不起作用,我已经解决了它并且它有效。我的问题是关于我发现的同一问题的另一种特定解决方案,因为我想了解其他解决方案背后的逻辑。
我遇到了以下循环数组旋转问题(在源代码下方):
给定一个由 N 个整数组成的数组 A。数组的旋转意味着每个元素右移一个索引,并且数组的最后一个元素移动到第一位。例如,数组 A = [3, 8, 9, 7, 6] 的旋转为 [6, 3, 8, 9, 7] (元素右移一个索引,6 移到第一位)。 目标是将数组 A 旋转 K 次;也就是A的每个元素都会右移K次。
我设法用以下 Python 代码解决了这个问题:
def solution(A , K):
N = len(A)
if N < 1 or N == K:
return A
K = K % N
for x in range(K):
tmp = A[N - 1]
for i in range(N - 1, 0, -1):
A[i] = A[i - 1]
A[0] = tmp
return A
然后,在以下网站https://www.martinkysel.com/codility-cyclicrotation-solution/ 上,我找到了以下针对同一问题的奇特解决方案:
def reverse(arr, i, j):
for idx in xrange((j - i + 1) / 2):
arr[i+idx], arr[j-idx] = arr[j-idx], arr[i+idx]
def solution(A, K):
l = len(A)
if l == 0:
return []
K = K%l
reverse(A, l - K, l -1)
reverse(A, 0, l - K -1)
reverse(A, 0, l - 1)
return A
有人能解释一下这个特殊的解决方案是如何工作的吗? (作者在他的网站上没有解释)
我的解决方案对于大型A 和K 表现不佳,其中K < N,例如:
A = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] * 1000
K = 1000
expectedResult = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] * 1000
res = solution(A, K) # 1455.05908203125 ms = almost 1.4 seconds
因为对于K < N,我的代码的时间复杂度为O(N * K),其中N是数组的长度。
对于大 K 和小 N (K > N),由于模运算 K = K % N,我的解决方案表现良好:
A = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
K = 999999999999999999999999
expectedRes = [2, 3, 4, 5, 6, 7, 8, 9, 10, 1]
res = solution(A, K) # 0.0048828125 ms, because K is torn down to 9 thanks to K = K % N
另一方面,另一种解决方案在所有情况下都表现出色,即使在 N > K 并且复杂度为 O(N) 时也是如此。
该解决方案背后的逻辑是什么?
感谢您的关注。
【问题讨论】:
-
你真的在问为什么
a, b = b, a交换a和b? -
不,我不知道。我了解它的作用,我不了解 3 个
reverse()调用以及其中的索引的相关计算。 -
this question 中有一些关于算法的信息。
标签: python arrays algorithm list