【问题标题】:Python Array RotationPython 数组旋转
【发布时间】:2013-06-25 09:04:51
【问题描述】:

所以我在 python 中实现了一个块交换算法。

我遵循的算法是这样的:

初始化 A = arr[0..d-1] 和 B = arr[d..n-1] 1) 执行以下操作,直到 A 的大小等于 B 的大小

a) 如果 A 更短,则将 B 分为 Bl 和 Br,使得 Br 相同 长度为 A。交换 A 和 Br 以将 ABlBr 更改为 BrBlA。现在一个 是在它的最后位置,所以在 B 的片段上重复。

b) 如果 A 更长,将 A 分成 Al 和 Ar,使得 Al 相同 长度为 B 交换 Al 和 B 以将 AlArB 更改为 BArAl。现在乙 是在它的最后位置,所以在 A 的片段上重复。

2) 最后当 A 和 B 大小相等时,块交换它们。

在这个网站上用 C 语言实现了相同的算法 - Array Rotation

我的python代码是

a = [1,2,3,4,5,6,7,8]

x = 2

n = len(a)


def rotate(a,x):
    n = len(a)

    if x == 0 or x == n:
        return a

    if x == n -x:
        print(a)
        for i in range(x):
            a[i], a[(i-x+n) % n] = a[(i-x+n) % n], a[i]
        print(a)
        return a

    if x < n-x:
        print(a)
        for i in range(x):
            a[i], a[(i-x+n) % n] = a[(i-x+n) % n], a[i]
        print(a)
        rotate(a[:n-x],x)
    else:
        print(a)
        for i in range(n-x):
            a[i], a[(i-(n-x) + n) % n] = a[(i-(n-x) + n) % n] , a[i]
        print(a)
        rotate(a[n-x:], n-x)

rotate(a,x)
print(a)

我在每个阶段都得到了正确的值,但是递归函数调用没有返回预期的结果,我似乎无法理解原因。有人可以解释我的递归有什么问题吗?以及可能的替代方案。

【问题讨论】:

    标签: python arrays recursion rotation swap


    【解决方案1】:

    您可以在 Python 中使用deque 旋转列表:

    >>> from collections import deque
    >>> d=deque([1,2,3,4,5])
    >>> d
    deque([1, 2, 3, 4, 5])
    >>> d.rotate(2)
    >>> d
    deque([4, 5, 1, 2, 3])
    >>> d.rotate(-2)
    >>> d
    deque([1, 2, 3, 4, 5])
    

    或者使用列表切片:

    >>> li=[1,2,3,4,5]
    >>> li[2:]+li[:2]
    [3, 4, 5, 1, 2]
    >>> li[-2:]+li[:-2]
    [4, 5, 1, 2, 3]
    

    请注意,符号约定与 deque.rotate 与切片相反。

    如果你想要一个具有相同符号约定的函数:

    def rotate(l, y=1):
       if len(l) == 0:
          return l
       y = -y % len(l)     # flip rotation direction
       return l[y:] + l[:y]
    
    >>> rotate([1,2,3,4,5],2)
    [4, 5, 1, 2, 3]
    >>> rotate([1,2,3,4,5],-22)
    [3, 4, 5, 1, 2]
    >>> rotate('abcdefg',3)
    'efgabcd'
    

    对于 numpy,只需使用 np.roll

    >>> a
    array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
    >>> np.roll(a, 1)
    array([9, 0, 1, 2, 3, 4, 5, 6, 7, 8])
    >>> np.roll(a, -1)
    array([1, 2, 3, 4, 5, 6, 7, 8, 9, 0])
    

    或者您可以使用上面相同 rotate 的 numpy 版本(再次注意符号与 np.roll 的区别):

    def rotate(a,n=1):
        if len(a) == 0:
            return a
        n = -n % len(a)     # flip rotation direction
        return np.concatenate((a[n:],a[:n]))  
    

    【讨论】:

    • 我可以按照您的建议使用很多 python。然而,它给了我一个挑战,我必须在不使用内部方法的情况下实施。如果您可以建议对上述代码进行修改,那就太好了
    • @dawg 如果 li 是 numpy.array,则添加不会连接两个数组,而是逐项添加。如何使用 numpy 数组进行旋转操作?
    • @dawg 我非常喜欢你的回答,我只是希望我早点看到这个答案,与此同时,我这样做了:np.concatenate((a[n:],a[:n]))
    • @dawg 根据 IPython %timeit,np.concatenate( ( a[n:], a[:n] ) ) 似乎快了 10 倍 :)
    • @SebMa: np.concatenate( ( a[n:], a[:n] ) ) 确实更快。对于较大的阵列,它确实会减慢速度。类似于我给出的 Python 答案。谢谢!我会补充的。
    【解决方案2】:

    Python 中数组旋转的简单简写语法是

    arr = arr[numOfRotations:]+arr[:numOfRotations]
    

    例子:

    arr = [1,2,3,4,5]
    rotations = 4
    then 
    
    arr = arr[4:]+arr[:4]
    

    给我们

    [5,1,2,3,4]

    【讨论】:

      【解决方案3】:

      我发现了一个问题,即对于较大的 k 值(其中 k 是旋转次数),我需要左右旋转,因此,我为任意大小的 k 实现了以下函数。

      右圆周旋转(从左到右:1234 -> 4123):

      def right_rotation(a, k):
         # if the size of k > len(a), rotate only necessary with
         # module of the division
         rotations = k % len(a)
         return a[-rotations:] + a[:-rotations]
      

      左圆周旋转(从右到左:1234 -> 2341):

      def left_rotation(a, k):
         # if the size of k > len(a), rotate only necessary with
         # module of the division
         rotations = k % len(a)
         return a[rotations:] + a[:rotations]
      

      来源:

      【讨论】:

        【解决方案4】:

        您真的需要实现块交换还是只是想旋转数组?在 python 中,您可以使用

        进行 CW 和 CWW 旋转
        zip(*arr[::-1])
        

        zip(*arr)[::-1]
        

        【讨论】:

        • 你能解释一下吗?
        • @LongHoang 这个答案实际上并没有回答这个问题,因为它在 2D 数组 上顺时针和逆时针旋转。我可能会在今天晚些时候删除这个答案。
        【解决方案5】:

        我希望当您将 a 的一部分传递给递归调用时,您不会再传递相同的变量。尝试将整个 a 和切片的上限/下限作为附加参数传递给函数。

        例如考虑这个函数:

        def silly(z):
          z[0] = 2
        

        我刚刚尝试了以下方法:

        >>> z = [9,9,9,9,9,9]
        >>> silly(z)
        >>> z
        [2, 9, 9, 9, 9, 9]
        >>> silly(z[3:])
        >>> z
        [2, 9, 9, 9, 9, 9]
        

        在哪里可以看到整个数组没有保留对切片的修改

        出于好奇,你得到了什么输出以及你期望什么输出?

        【讨论】:

          【解决方案6】:

          您可以使用此代码在 python 数组中进行左旋转

          import copy
          def leftRotate(arr,n) :
              _arr = copy.deepcopy(arr)
              for i in range(len(arr)-n):
                  arr[i] = arr[i+n]
              for j in range(n):
                  arr[(len(arr)-n)+j] = _arr[j]
          
          arr = [1, 2, 3, 4, 5, 6, 7] 
          leftRotateby = 3
          leftRotate(arr,leftRotateby)
          print arr 
          #output:: [4, 5, 6, 7, 1, 2, 3]
          

          【讨论】:

          • @Ângelo Polotto 的回答是正确的,这个在极端情况下不起作用。
          【解决方案7】:
          def leftRotation():
              
              li = [int(x) for x in input().split()]
          
              d = int(input())
              ans = (li[d:]+li[0:d])
          
              for i in ans:
                  print(i,end=' ')
              print()
              
          leftRotation()
          

          【讨论】:

          • 您能解释一下原始代码有什么问题吗?
          • 原代码没有问题。我只是想分享一种我使用切片的不同方法。
          【解决方案8】:
          def rotLeft(a, d):
              lenght=len(a)
              for j in range(0,d):
               temp = a[0]
               
               for i in range(lenght-1):
                  a[i] = a[i+1]
               a[lenght-1] = temp
              # Write your code here
              return a    
              
          if __name__ == '__main__':
              fptr = open(os.environ['OUTPUT_PATH'], 'w')
          
              first_multiple_input = input().rstrip().split()
          
              n = int(first_multiple_input[0])
          
              d = int(first_multiple_input[1])
          
              a = list(map(int, input().rstrip().split()))
          
              result = rotLeft(a, d)
          
              fptr.write(' '.join(map(str, result)))
              fptr.write('\n')
          
              fptr.close()
          

          【讨论】:

            【解决方案9】:

            阵列旋转:-

            print("Right:1,Left:2")
            op=int(input())
            par=[1,2]
            if op not in par:
               print("Invalid Input!!")
               
            else:  
              arr=list(map(int,input().strip().split()))
              shift=int(input())
              if op ==1:
                right=arr[-shift:]+arr[:-shift]
                print(right)
              elif op==2:
                left=arr[shift:]+arr[:shift]  
                print(left)
            

            输出:-`

            Right:1,Left:2
            1
            12 45 78 91 72 64 62 43
            2
            [62, 43, 12, 45, 78, 91, 72, 64]`
            

            【讨论】:

              【解决方案10】:
              def rotate(nums=[1,2,3,4,5,6,7], k=3):
                  i=0
                  while i < k:
                      pop_item = nums.pop()
                      nums.insert(0, pop_item)
                      i += 1
              
                  return nums  # [5,6,7,1,2,3,4]
              

              【讨论】:

              • 欢迎来到 StackOverflow。虽然此代码可能会回答问题,但提供有关 如何 和/或 为什么 解决问题的附加上下文将提高​​答案的长期价值。
              【解决方案11】:

              如果您不应该使用双端队列或切片:

              def rotate(array: List[int], k: int) -> List[int]:
                  # loop through the array from -k to array_size - k
                  return [array[i] for i in range(-k, len(array) - k)]
              

              【讨论】:

                猜你喜欢
                • 2021-11-02
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2016-07-18
                • 2019-12-10
                • 2014-12-23
                • 1970-01-01
                相关资源
                最近更新 更多