简体   繁体   English

数组循环旋转说明

[英]Cyclic rotation of array explanation

Premise: My question is not a duplicate of Cyclic rotation in Python .前提:我的问题不是Python循环旋转的重复。 I am not asking how to resolve the problem or why my solution does not work, I have already resolved it and it works.我不是在问如何解决问题或为什么我的解决方案不起作用,我已经解决了它并且它有效。 My question is about another particular solution to the same problem I found, because I would like to understand the logic behind the other solution.我的问题是关于我发现的同一问题的另一个特定解决方案,因为我想了解另一个解决方案背后的逻辑。

I came across the following cyclic array rotation problem (below the sources):我遇到了以下循环数组旋转问题(来源下方):

An array A consisting of N integers is given.给出一个由 N 个整数组成的数组 A。 Rotation of the array means that each element is shifted right by one index, and the last element of the array is moved to the first place.数组的旋转意味着每个元素右移一个索引,数组的最后一个元素移到第一位。 For example, the rotation of array A = [3, 8, 9, 7, 6] is [6, 3, 8, 9, 7] (elements are shifted right by one index and 6 is moved to the first place).例如,数组 A = [3, 8, 9, 7, 6] 的旋转是 [6, 3, 8, 9, 7] (元素右移一个索引,6 移到第一位)。 The goal is to rotate array AK times;目标是将数组旋转 AK 次; that is, each element of A will be shifted to the right K times.也就是说,A 的每个元素都将向右移动 K 次。

which I managed to solve with the following Python code:我设法用以下 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

Then, on the following website https://www.martinkysel.com/codility-cyclicrotation-solution/ , I have found the following fancy solution to the same problem:然后,在以下网站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

Could someone explain me how this particular solution works?有人能解释一下这个特定的解决方案是如何工作的吗? (The author does not explain it on his website) (作者在他的网站上没有解释)

My solution does not perform quite well for large A and K , where K < N , eg:我的解决方案对于大AK表现不佳,其中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

Because for K < N , my code has a time complexity of O(N * K) , where N is the length of the array.因为对于K < N ,我的代码的时间复杂度为O(N * K) ,其中 N 是数组的长度。 For large K and small N ( K > N ), my solution performs well thanks to the modulo operation K = 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

The other solution, on the other hand, performs greatly in all cases, even when N > K and has a complexity of O(N) .另一方面,另一种解决方案在所有情况下都表现出色,即使N > K并且具有O(N)的复杂度。

What is the logic behind that solution?该解决方案背后的逻辑是什么?

Thank you for the attention.感谢您的关注。

Let me talk first the base case with K < N , the idea in this case is to split the array in two parts A and B , A is the first NK elements array and B the last K elements.让我先谈谈K < N的基本情况,这种情况下的想法是将数组分为AB两部分, A是第一个 NK 元素数组, B是最后 K 个元素。 the algorithm reverse A and B separately and finally reverse the full array (with the two part reversed separately).该算法分别反转AB ,最后反转整个数组(将两部分分别反转)。 To manage the case with K > N , think that every time you reverse the array N times you obtain the original array again so we can just use the module operator to find where to split the array (reversing only the really useful times avoiding useless shifting).要管理K > N的情况,请认为每次反转数组 N 次都会再次获得原始数组,因此我们可以使用模块运算符来查找拆分数组的位置(仅反转真正有用的时间,避免无用的移位)。

Graphical Example图形示例

A graphical step by step example can help understanding better the concept.图形化的分步示例可以帮助更好地理解概念。 Note that注意

  • The bold line indicate the the splitting point of the array ( K = 3 in this example);粗线表示数组的分裂点(本例中K = 3 );
  • The red array indicate the input and the expected output.红色数组表示输入和预期输出。

Starting from:从...开始:

起始数组

look that what we want in front of the final output will be the last 3 letter reversed, for now let reverse it in place (first reverse of the algorithm):看看我们想要在最终输出前面的将是最后 3 个字母反转,现在让我们将其反转到位(算法的第一个反转):

first_pass_array

now reverse the first NK elements (second reverse of the algorithm):现在反转第一个 NK 元素(算法的第二个反转):

second_pass_array

we already have the solution but in the opposite direction, we can solve it reversing the whole array (third and last reverse of the algorithm):我们已经有了解决方案,但在相反的方向上,我们可以通过反转整个数组(算法的第三个和最后一个反转)来解决它:

final_array

Here the final output, the original array cyclical rotated with K = 3.这里是最终输出,原始数组循环旋转,K = 3。

Code Example代码示例

Let give also another step by step example with python code, starting from:让我们再举一个 Python 代码的分步示例,从:

A = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
K = 22
N = len(A)

we find the splitting index:我们找到分裂指数:

K = K%N
#2

because, in this case, the first 20 shift will be useless, now we reverse the last K (2) elements of the original array:因为,在这种情况下,前 20 个移位将无用,现在我们反转原始数组的最后 K (2) 个元素:

reverse(A, N-K, N-1)
# [1, 2, 3, 4, 5, 6, 7, 8, 10, 9]

as you can see 9 and 10 has been shift, now we reverse the first NK elements:正如你所看到的 9 和 10 已经移位,现在我们反转第一个 NK 元素:

reverse(A, 0, N-K-1)
# [8, 7, 6, 5, 4, 3, 2, 1, 10, 9]

And, finally, we reverse the full array:最后,我们反转整个数组:

reverse(A, 0, N-1)
# [9, 10, 1, 2, 3, 4, 5, 6, 7, 8]

Note that reversing an array have time complexity O(N).请注意,反转数组的时间复杂度为 O(N)。

Here is a very simple solution in Ruby.这是一个非常简单的 Ruby 解决方案。 (scored 100% in codility) Remove the last element in the array, and insert it in the beginning. (codility 得分 100%) 删除数组中的最后一个元素,并将其插入到开头。

def solution(a, k)
  if a.empty?
    return []
  end
  modified = a
  1.upto(k) do 
    last_element = modified.pop
    modified = modified.unshift(last_element)
  end
  return modified
end

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM