块交换算法用于阵列旋转的详细指南

155 阅读4分钟

这篇文章讨论了块交换算法。它用于将一个数组旋转任意数量的位置,其时间复杂度为O(N),空间复杂度为O(1)。

目录:

  1. 阵列旋转的问题陈述
  2. 区块互换算法
  3. 例子区块交换算法的试运行
  4. 区块互换算法的实现
  5. 区块互换算法的时间复杂度
  6. 区块互换算法的空间复杂度

让我们开始学习区块交换算法。

阵列旋转的问题声明

在我们讨论算法之前,我们必须先看看旋转数组的实际含义是什么。一个数组可以在任何方向(左或右)旋转任意次数。

假设A=[1,2,3,4,5] 。

向左旋转一次。A = [2,3,4,5,1]
向右旋转一次。A = [5,1,2,3,4]
向左旋转三个位置。A = [4,5,1,2,3]
另外,请注意,向左旋转D次,相当于向右旋转N次。

因为,A=[1,2,3,4,5]。

向左旋转2位。A = [3,4,5,1,2].
这相当于向右旋转3次(N - D => 5-2 = 3)。A = [3,4,5,1,2].

有许多方法来旋转一个数组。一些方法需要辅助空间,而另一些方法需要对数组进行一次以上的遍历。然而,块交换算法提供了一种有效的方法来执行旋转操作。我们将在本文中详细讨论它。

反转算法提供了另一种相同的方法。请参考这篇文章,以获得一个良好的洞察力。

区块互换算法

区块交换算法的步骤是。

  1. 将数组分为两部分,A = arr[0...d-1],B = arr[d...n-1]。

  2. 当A的大小不等于B的大小时,这样做:
    2.1 如果A的大小小于B,用B的一个大小等于A的子数组交换A,并且不与A相邻。

  3. 交换A和B

让我们详细了解一下步骤2。

在2.1中,A的大小小于B的大小,所以我们将A与B中的一个子数交换,使其与A的大小相同,并且不与A相邻。
对于arr = [A][B] 和B = [B1][B2] => arr = [A][B1][B2] 其中B2的大小等于A的大小,我们将[A]和[B2]交换,结果Arr = [B2][B1][A] 。
现在,[A]在它的正确位置。继续计算arr = [B2][B1]。

在2.2中,B的大小小于A的大小,所以我们将B与A中的一个子数交换,使其与B的大小相同,并且不与B相邻。
对于arr = [A][B] 和A = [A1][A2] => arr = [A1][A2][B] 其中A1的大小等于B的大小,我们将[A1]和[B]交换,其结果是arr = [B][A2] [A1] 。现在,[B]在它的正确位置。继续计算arr = [A2][A1]。

例子:区块互换算法的试运行

考虑arr = [1,2,3,4,5], N = 5, d = 2.

步骤1:A = arr[0...1] = [1,2] & B = arr[2...4] = [3,4,5]

第2步:由于大小(A)<大小(B),将A与B2交换,其中B2 = [4,5] & B1 = [3]。因此,A = [B2] = [4,5] ,B = [B1][A] = [3,1,2]。

现在,继续计算[4,5,3],它对应于[B2][B1],因为[A]是在它的最终位置。

A = arr[0...1] = [4,5] & B = [2...2] = [3]
由于大小(A)>大小(B),用A1交换B,A1 = [4] & A2 = [5]。所以,A1 = [B] = [3] & B = [A1] = 4。而arr = [3,5,4] = [B][A2][A1] 。

现在,对[A2][A1]=[5,4]进行递归。

所以,对于这次迭代,arr = [5,4], N = 2, d = 2.因为,d==N,所以返回数组。

因此,结果数组是[3,5,4,1,2],这也是预期结果。

区块互换算法的实现

以下是块交换算法在Java中的实现:

public static void rotate(int arr[], int i, int d, int n)
{
    if(d == 0 || d == n)
    return;

    if(d == n-d)  //Size of both the arrays is equal
    {
        swap(arr, i, n - d + i, d);   //swap(arr, i, i+d);
        return
    }
    if(d < n-d)
    {
        swap(arr, i, n-d+i, d);
        rotate(arr, i, d, n-d);
    }
    else
    {
        swap(arr, i, d, n-d);
        rotate(arr, n-d+i, 2*d - n,d);
    }
}

 public static void swap(int arr[], int s, int e, int d)
 {
     for(int i=0;i<d;i++)
     {
            int temp = arr[s + i];
            arr[s + i] = arr[e + i];
            arr[e + i] = temp;
     }
 }

以下是区块交换算法在Java中的实现:

void rotate(int arr[], int i, int d, int n)
{
    if(d == 0 || d == n)
    return;

    if(d == n-d)  //Size of both the arrays is equal
    {
        swap(arr, i, n - d + i, d);   //swap(arr, i, i+d);
        return
    }
    if(d < n-d)
    {
        swap(arr, i, n-d+i, d);
        rotate(arr, i, d, n-d);
    }
    else
    {
        swap(arr, i, d, n-d);
        rotate(arr, n-d+i, 2*d - n,d);
    }
}

void swap(int arr[], int s, int e, int d)
{
     for(int i=0;i<d;i++)
     {
            int temp = arr[s + i];
            arr[s + i] = arr[e + i];
            arr[e + i] = temp;
     }
}

区块互换算法的时间复杂度

这个算法需要O(N)时间。

这是因为,在每次迭代中,我们交换d个元素,之后d个元素会出现在它们的正确位置。剩余的n-d个元素被传递给下一个函数调用,同样的操作被重复,直到d变成等于n-d。这表明时间复杂度将是O(N),每个元素至少被交换一次。

块交换算法的空间复杂度

没有使用辅助空间,所以块交换算法的空间复杂度是O(1)。

通过OpenGenus的这篇文章,你一定对块交换算法有了完整的了解。