Операция левого поворота на массиве размером n сдвигов - PullRequest
1 голос
/ 26 марта 2019

Я пытаюсь реализовать вращение влево на массиве размером n сдвигов. Например, у меня есть

array = {1,2,3,4,5};

а у меня количество смен:

сдвиги = 2;

После обработки массива он должен выглядеть так:

массив = {3,4,5,1,2};

Я реализовал это с двумя для петель:

var array = new int[]{1,2,3,4,5};
var shifts =3;
var temp = 0;
for(var j = 0; j < shifts; j++){
     temp = array[0];
     for(var i = 0; i < array.Length -1; i++){
         array[i] = array[i + 1];
     }
     array[array.Length-1] = temp;
}
for(var i =0 ; i< array.Length; i++){
    System.Console.Write(array[i]+ " ");
}
 Console.Read();

И это работает, но не проходит некоторые тесты с большим количеством чисел в массиве, и я получаю Завершено из-за тайм-аута Ошибка;

Есть ли способы реализовать вращение влево в одном цикле?

Ответы [ 3 ]

3 голосов
/ 26 марта 2019

Я думаю, что это так же эффективно, как и вращение массива на месте. Работает как для левого и правого поворота, в зависимости от знака rotateBy:

private static void Rotate<T>(T[] array, int rotateBy)
{
    rotateBy %= array.Length;
    // Nothing to do?
    if (rotateBy == 0)
        return;
    // Normalize it to a right rotation
    if (rotateBy < 0)
        rotateBy = array.Length + rotateBy;
    // Allocate the smallest possible temp array
    if (rotateBy > array.Length / 2)
    {
        T[] temp = new T[array.Length - rotateBy];
        Array.Copy(array, 0, temp, 0, array.Length - rotateBy);
        Array.Copy(array, array.Length - rotateBy, array, 0, rotateBy);
        Array.Copy(temp, 0, array, rotateBy, array.Length - rotateBy);
    }
    else
    {
        T[] temp = new T[rotateBy];
        Array.Copy(array, array.Length - rotateBy, temp, 0, rotateBy);
        Array.Copy(array, 0, array, rotateBy, array.Length - rotateBy);
        Array.Copy(temp, 0, array, 0, rotateBy);  
    }
}
2 голосов
/ 26 марта 2019

Это обман, но решение LINQ может быть:

var array = Enumerable.Range(0, 100).ToArray();
var shiftBy = 2;
var shifted = array.Skip(shiftBy).Concat(array.Take(shiftBy)).ToArray();

Если ваша задача просто «просмотреть» массив таким преобразованным способом, чтобы избежать создания нового массива, исключите конец .ToArray() и итерируйте по IEnumerable<int> напрямую.

0 голосов
/ 26 марта 2019

Получил это, используя вращающийся буфер с размером количества смен.

static void ShiftLeft(int[] array, int shifts)
{
    int length = array.Length;
    int actualShifts = shifts % length;
    if (actualShifts == 0) return;
    int[] buffer = new int[actualShifts];
    Array.Copy(array, buffer, actualShifts);
    int indexAddition = actualShifts - (length % actualShifts);
    for (int i = length - 1; i >= 0; i--)
    {
        int current = array[i];
        int bufferIndex = (i + indexAddition) % actualShifts;
        array[i] = buffer[bufferIndex];
        buffer[bufferIndex] = current;
    }
}

РЕДАКТИРОВАТЬ: Как указал @ canton7, кольцевой буфер добавляет ненужную сложность. Ниже следует сделать, в основном, ответ @ canton7, хотя @ canton7 его ответ все еще более эффективен из-за меньшего буфера:

int length = array.Length;
int actualShifts = shifts % length;
if (actualShifts == 0) return;
int[] buffer = new int[actualShifts];
Array.Copy(array, buffer, actualShifts);
Array.Copy(array, actualShifts, array, 0, length - actualShifts);
Array.Copy(buffer, 0, array, length - actualShifts, actualShifts);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...