给定一个n
整数数组和一个数字d
,在数组上执行左旋转。然后将更新的数组打印为一行以空格分隔的整数。
示例输入:
5 4
1 2 3 4 5
第一行包含两个以空格分隔的整数,表示n
(整数)和d
(必须执行的左旋转数)的相应值。
第二行包含n
空格分隔的整数,用于描述数组初始状态的各个元素。
示例输出:
5 1 2 3 4
static void Main(String[] args)
{
string[] arr_temp = Console.ReadLine().Split(' ');
int n = Int32.Parse(arr_temp[0]);
int d = Int32.Parse(arr_temp[1]);
string[] arr = Console.ReadLine().Split(' ');
string[] ans = new string[n];
for (int i = 0; i < n; ++i)
{
ans[(i + n - d) % n] = arr[i];
}
for (int j = 0; j < n; ++j)
{
Console.Write(ans[j] + " ");
}
}
如何使用更少的内存来解决这个问题?
答案 0 :(得分:3)
其实你问过两个问题:
如何高效旋转数组?
和
如何使用更少内存来解决此问题?
通常效率和低内存使用是互斥的。所以我将回答你的第二个问题,仍然在该内存约束下提供最有效的实现。
以下方法可用于左(通过负计数)或右(通过正计数)旋转。它使用 O(1)空间(单个元素)和 O(n * min(d,n - d))数组元素复制操作( O(min) (d,n - d))数组块复制操作)。在最坏的情况下,它执行 O(n / 2)块复制操作。
算法正在利用
这一事实rotate_left(n,d)== rotate_right(n,n - d)
这是:
var array = Enumerable.Range(1, 5).ToArray(); // { 1, 2, 3, 4, 5 }
array.Rotate(-4); // { 5, 1, 2, 3, 4 }
示例用法,例如:
{{1}}
答案 1 :(得分:3)
在大多数情况下,这将使用更少的内存,因为第二个数组仅与移位一样大。
public static void Main(string[] args)
{
int[] n = { 1, 2, 3, 4, 5 };
LeftShiftArray(n, 4);
Console.WriteLine(String.Join(",", n));
}
public static void LeftShiftArray<T>(T[] arr, int shift)
{
shift = shift % arr.Length;
T[] buffer = new T[shift];
Array.Copy(arr, buffer, shift);
Array.Copy(arr, shift, arr, 0, arr.Length - shift);
Array.Copy(buffer, 0, arr, arr.Length - shift, shift);
}
答案 2 :(得分:1)
你真的需要移动物体吗?如果没有,你可以改为改变索引。
答案 3 :(得分:1)
我已经通过以下代码解决了Hackerrank的挑战。希望能帮助到你。
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
namespace ConsoleApp1
{
class ArrayLeftRotationSolver
{
TextWriter mTextWriter;
public ArrayLeftRotationSolver()
{
mTextWriter = new StreamWriter(@System.Environment.GetEnvironmentVariable("OUTPUT_PATH"), true);
}
public void Solve()
{
string[] nd = Console.ReadLine().Split(' ');
int n = Convert.ToInt32(nd[0]);
int d = Convert.ToInt32(nd[1]);
int[] a = Array.ConvertAll(Console.ReadLine().Split(' '), aTemp => Convert.ToInt32(aTemp))
;
int[] result = rotLeft(a, d);
mTextWriter.WriteLine(string.Join(" ", result));
mTextWriter.Flush();
mTextWriter.Close();
}
private int[] rotLeft(int[] arr, int shift)
{
int n = arr.Length;
shift %= n;
int[] vec = new int[n];
for (int i = 0; i < n; i++)
{
vec[(n + i - shift) % n] = arr[i];
}
return vec;
}
static void Main(string[] args)
{
ArrayLeftRotationSolver solver = new ArrayLeftRotationSolver();
solver.Solve();
}
}
}
答案 4 :(得分:1)
这个问题可能会有些棘手,但如果熟悉队列和堆栈,也可以采用简单的解决方案。 我要做的就是定义一个Queue(它将包含给定的数组)和一个Stack。 接下来,我只需要将出队索引推入堆栈,并将弹出的索引排入队列,最后返回队列。 听起来令人困惑?检查以下代码:
static int[] rotLeft(int[] a, int d) {
Queue<int> queue = new Queue<int>(a);
Stack<int> stack = new Stack<int>();
while(d > 0)
{
stack.Push(queue.Dequeue());
queue.Enqueue(stack.Pop());
d--;
}
return queue.ToArray();
}
答案 5 :(得分:0)
这是非常直接的答案。 主要是你如何选择起始索引。
public static List<int> rotateLeft(int d, List<int> arr) {
int n = arr.Count;
List<int> t = new List<int>();
int h = d;
for (int j = 0; j < n; j++)
{
if ((j + d) % n == 0)
{
h = 0;
}
t.Add(arr[h]);
h++;
}
return t;
}
使用此代码,我已成功提交黑客等级问题,
答案 6 :(得分:0)
如果查看约束,您将看到d <= n(旋转数<=数组中的元素数)。因此,可以在1行中解决。
static int[] rotLeft(int[] a, int d)
{
return a.Skip(d).Concat(a.Take(d)).ToArray();
}
答案 7 :(得分:0)
这是什么?
public static void RotateArrayAndPrint(int[] n, int rotate)
{
for (int i = 1; i <= n.Length; i++)
{
var arrIndex = (i + rotate) > n.Length ? n.Length - (i + rotate) : (i + rotate);
arrIndex = arrIndex < 0 ? arrIndex * -1 : arrIndex;
var output = n[arrIndex-1];
Console.Write(output + " ");
}
}
答案 8 :(得分:0)
O(1)空间,O(n)时间解
我认为从理论上讲这是最佳的,因为它可以进行一次就地交换和每个内部循环1个临时变量交换。
但是我怀疑O(d)空间解决方案在现实生活中会更快,这是因为更少的代码分支(更少的CPU命令管道重置)和缓存位置(主要是顺序访问与d元素步骤相比)。
static int[] RotateInplaceLeft(int[] a, int d)
{
var swapCount = 0;
//get canonical/actual d
d = d % a.Length;
if(d < 0) d += a.Length;
if(d == 0) return a;
for (var i = 0; swapCount < a.Length; i++) //we're done after a.Length swaps
{
var dstIdx = i; //we need this becasue of ~this: https://youtu.be/lJ3CD9M3nEQ?t=251
var first = a[i]; //save first element in this group
for (var j = 0; j < a.Length; j++)
{
var srcIdx = (dstIdx + d) % a.Length;
if(srcIdx == i)// circled around
{
a[dstIdx] = first;
swapCount++;
break; //hence we're done with this group
}
a[dstIdx] = a[srcIdx];
dstIdx = srcIdx;
swapCount++;
}
}
return a;
}
答案 9 :(得分:0)
这是我的尝试。这很容易,但是由于某些原因,它在大数据块上超时:
int arrayLength = arr.Length;
int tmpCell = 0;
for (int rotation = 1; rotation <= d; rotation++)
{
for (int i = 0; i < arrayLength; i++)
{
if (arr[i] < arrayElementMinValue || arr[i] > arrayElementMaxValue)
{
throw new ArgumentException($"Array element needs to be between {arrayElementMinValue} and {arrayElementMaxValue}");
}
if (i == 0)
{
tmpCell = arr[0];
arr[0] = arr[1];
}
else if (i == arrayLength - 1)
{
arr[arrayLength - 1] = tmpCell;
}
else
{
arr[i] = arr[i + 1];
}
}
}
答案 10 :(得分:0)
使用IEnumerables更好吗?由于它不会执行所有这些数学运算,因此不会分配那么多数组,等等
public static int[] Rotate(int[] elements, int numberOfRotations)
{
IEnumerable<int> newEnd = elements.Take(numberOfRotations);
IEnumerable<int> newBegin = elements.Skip(numberOfRotations);
return newBegin.Union(newEnd).ToArray();
}
如果您实际上不需要返回数组,甚至可以删除.ToArray()并返回IEnumerable
用法:
void Main()
{
int[] n = { 1, 2, 3, 4, 5 };
int d = 4;
int[] rotated = Rotate(n,d);
Console.WriteLine(String.Join(" ", rotated));
}
答案 11 :(得分:0)
一个古老的问题,但我想我将仅使用一个中间数组(如果包含LINQ Take表达式,则为2)来添加另一种可能的解决方案。该代码向右旋转,而不是向左旋转,但是仍然可能有用。
public static Int32[] ArrayRightRotation(Int32[] A, Int32 k)
{
if (A == null)
{
return A;
}
if (!A.Any())
{
return A;
}
if (k % A.Length == 0)
{
return A;
}
if (A.Length == 1)
{
return A;
}
if (A.Distinct().Count() == 1)
{
return A;
}
for (var i = 0; i < k; i++)
{
var intermediateArray = new List<Int32> {A.Last()};
intermediateArray.AddRange(A.Take(A.Length - 1).ToList());
A = intermediateArray.ToArray();
}
return A;
}
答案 12 :(得分:0)
将项目置于位置0,并在末尾添加。删除位置0处的项目。重复n次。
List<int> iList = new List<int>();
private void shift(int n)
{
for (int i = 0; i < n; i++)
{
iList.Add(iList[0]);
iList.RemoveAt(0);
}
}
答案 13 :(得分:0)
希望这会有所帮助。
public static int[] leftrotation(int[] arr, int d)
{
int[] newarr = new int[arr.Length];
var n = arr.Length;
bool isswapped = false;
for (int i = 0; i < n; i++)
{
int index = Math.Abs((i) -d);
if(index == 0)
{
isswapped = true;
}
if (!isswapped)
{
int finalindex = (n) - index;
newarr[finalindex] = arr[i];
}
else
{
newarr[index] = arr[i];
}
}
return newarr;
}
答案 14 :(得分:0)
我曾尝试在C#中使用堆栈和队列来实现输出,如下所示:
public int[] rotateArray(int[] A, int rotate)
{
Queue<int> q = new Queue<int>(A);
Stack<int> s;
while (rotate > 0)
{
s = new Stack<int>(q);
int x = s.Pop();
s = new Stack<int>(s);
s.Push(x);
q = new Queue<int>(s);
rotate--;
}
return q.ToArray();
}
答案 15 :(得分:0)
我也试过这个,下面是我的方法...... 谢谢
public static int[] RotationOfArray(int[] A, int k)
{
if (A == null || A.Length==0)
return null;
int[] result =new int[A.Length];
int arrayLength=A.Length;
int moveBy = k % arrayLength;
for (int i = 0; i < arrayLength; i++)
{
int tmp = i + moveBy;
if (tmp > arrayLength-1)
{
tmp = + (tmp - arrayLength);
}
result[tmp] = A[i];
}
return result;
}
答案 16 :(得分:-1)
假设我有一个整数'Arr'数组。要旋转数组'n',您可以执行以下操作:
static int[] leftRotation(int[] Arr, int n)
{
int tempVariable = 0;
Queue<int> TempQueue = new Queue<int>(a);
for(int i=1;i<=d;i++)
{
tempVariable = TempQueue.Dequeue();
TempQueue.Enqueue(t);
}
return TempQueue.ToArray();`
}
如果有任何意见,请告诉我。谢谢!