题目
给定一个大小为 N 的整数数组 arr[] 和一个整数,任务是将数组元素向左旋转 d 个位置。
Examples:
Input:
arr[] = {1, 2, 3, 4, 5, 6, 7}, d = 2
Output: 3 4 5 6 7 1 2
Input: arr[] = {3, 4, 5, 6, 7, 1, 2}, d=2
Output: 5 6 7 1 2 3 4
方法1:使用临时数组
- 首先将索引 d 到 N-1 的元素存储到临时数组中。
- 然后将原始数组的前 d 个元素存储到 temp 数组中。
- 将临时数组的元素复制回原始数组
using System;
namespace csharptest
{
public class GFG
{
public static void PrintTheArray(int[] arr, int n)
{
for (int i = 0; i < n; i++)
{
Console.Write(arr[i].ToString() + " ");
}
}
public static void Rotate(int[] arr, int d, int n)
{
int[] temp = new int[n];
int k = 0;
for (int i = d; i < n; i++)
{
temp[k] = arr[i];
k++;
}
for (int i = 0; i < d; i++)
{
temp[k] = arr[i];
k++;
}
for (int i = 0; i < n; i++)
{
arr[i] = temp[i];
}
}
static void Main(string[] args)
{
Console.WriteLine("Main start ...");
int[] arr = {1, 2, 3, 4, 5, 6, 7};
var N = arr.Length;
var d = 2;
GFG.Rotate(arr, d, N);
GFG.PrintTheArray(arr, N);
Console.WriteLine("\nMain end ...");
}
}
}
Output
3 4 5 6 7 1 2
时间复杂度:O(N)
空间杂度:O(N)
方法2:一个一个地旋转
思路:
- 在每次迭代中,将元素循环向左移动一个位置(即,第一个元素变为最后一个元素)。
- 执行此操作 d 次以将元素向左旋转 d 位置。
步骤:
- 将数组向左旋转一个位置。 为此,请执行以下操作:
将数组的第一个元素存储在临时变量中。
将原始数组中的其余元素移动一位。
使用临时变量更新数组的最后一个索引。 - 对所需的左转次数重复上述步骤。
public static void Rotate2(int[] arr, int d, int n)
{
var p = 1;
while (p <= d)
{
var last = arr[0];
for (int i = 0; i < n - 1; i++)
{
arr[i] = arr[i + 1];
}
arr[n - 1] = last;
p++;
}
for (int i = 0; i < n; i++)
{
Console.Write(arr[i].ToString() + " ");
}
}
时间复杂度:O(N * d)
空间杂度:O(1)
方法3:方法2的扩展
说明:
Let arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12} and d = 3
First step:
=> First set is {1, 4, 7, 10}.
=> Rotate this set by one position to the left.
=> This set becomes {4, 7, 10, 1}
=> Array arr[] = {4, 2, 3, 7, 5, 6, 10, 8, 9, 1, 11, 12}
Second step:
=> Second set is {2, 5, 8, 11}.
=> Rotate this set by one position to the left.
=> This set becomes {5, 8, 11, 2}
=> Array arr[] = {4, 5, 3, 7, 8, 6, 10, 11, 9, 1, 2, 12}
Third step:
=> Third set is {3, 6, 9, 12}.
=> Rotate this set by one position to the left.
=> This set becomes {6, 9, 12, 3}
=> Array arr[] = {4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3}
步骤:
- 执行 d%n 以将 d 的值保持在数组的范围内,其中 d 是数组旋转的次数,N 是数组的大小。
- 计算 GCD(N, d) 以将数组划分为集合。
- 从 0 到从 GCD 获得的值运行一个 for 循环。
将 arr[i] 的值存储在一个临时变量中(i 的值表示集合数)。
运行 while 循环以根据集合更新值。 - 退出 while 循环后,将 arr[j] 的值分配为临时变量的值(j 的值表示第 i 个集合的最后一个元素)。
static int gcd(int a, int b)
{
if (b == 0)
return a;
else
return gcd(b, a % b);
}
static void leftRotate(int[] arr, int d, int n)
{
int i, j, k, temp;
/* To handle if d >= n */
d = d % n;
int g_c_d = gcd(d, n);
for (i = 0; i < g_c_d; i++) {
/* move i-th values of blocks */
temp = arr[i];
j = i;
while (true) {
k = j + d;
if (k >= n)
k = k - n;
if (k == i)
break;
arr[j] = arr[k];
j = k;
}
arr[j] = temp;
}
}
时间复杂度:O(N)
空间杂度:O(1)