Member 12642406 Ответов: 3

Как в C# повернуть список вправо на указанное количество мест?


Мне дана эта строка кода в частности:

public void Test8(List<int> items, int places)


Задача для этой задачи состоит в том, чтобы придумать решение, при котором я смогу повернуть список вправо на указанное количество мест. Вращение списка можно рассматривать как круговое, что означает, что элементы, которые выпадают из конца, оборачиваются вокруг начала, и наоборот.

Как я могу сделать это правильный путь? Есть ли несколько способов сделать это вручную, не используя какой-либо причудливый код?

Пример:
Initial Array or List: 20, 30, 40, 50,60, 70
Rotated to the right by 3 places: 50, 60, 70, 20, 30, 40.


Что я уже пробовал:

public void Test8(List<int> items, int places)
{
    int rotate = places;
    int[] results = new int[items.Count];

    for (int i = 0; i < items.Count; i++)
    {
        results[i] = items[(i + rotate) % items.Count];
    }
}

3 Ответов

Рейтинг:
21

Leo Chapiro

Попробовать это:

public void Test8(List<int> items, int places)
{ 
    int nItem;

    for (int i = 0; i < places; i++)
    {
        nItem = items[items.Count - 1];     // get the last item of the list
        items.RemoveItem(items.Count - 1);  // remove this item from the end  ...
        items.InsertItem(0, nItem);         // ... and insert this (last) item in front of the list
    }
}


Member 12642406

Я добавил код, который вы предложили, но входные данные все время противоречивы, что приводит к провалу теста во всех 5 запусках. Посмотрите на скриншот, который я сделал. - и GT; http://imgur.com/3qTOxch

Member 12642406

Ничего, у меня тоже есть работа. Писал что-то не то.

Richard Deeming

Это сработает, но не очень эффективно. :)

Каждый раз, когда вы InsertItem(0, ...), каждый другой элемент в списке должен быть перемещен на одно место.

Я был бы склонен использовать CopyTo, RemoveRange и InsertRange.

Рейтинг:
2

Richard Deeming

Немного более эффективная версия решения 1:

public void Test8(List<int> items, int places)
{
    // Handle cases where the number of places is greater than or equal to the number of items:
    places %= items.Count;
    if (places == 0) return;
    
    int[] range = new int[places];
    items.CopyTo(items.Count - places, range, 0, places);
    items.RemoveRange(items.Count - places, places);
    items.InsertRange(0, range);
}


Рейтинг:
1

Patrice T

У вас есть в основном 2 техники
- Поворот с копией в новый список
- Вращение на месте

Вращение с копией-это техника решения 1.
Чтобы вычислить новое положение элемента, вы должны применить формулу:
NewPosition= (OldPosition+ Rotation) % SizeOfList

Вращение на месте
Только вращение 1 и -1 являются практичными. Вы просто должны повторить столько раз, сколько нужно.
- псевдокод

if (rotation== -1)
{
    tmp= list[0]
    for scan= 1; scan < list.count; scan++)
    {
        list[scan-1]= list[scan];
    }
    list[list.count-1]= tmp;
}
else
{
    tmp= list[list.count-1]
    for scan= list.count-1; scan >=0; scan--)
    {
        list[scan]= list[scan-1];
    }
    list[0]= tmp;
}


0x01AA

Только игра ума:
Есть и третий вариант - "виртуальная ротация". Я имею в виду что-то вроде
listIndex= (userIndex + rotationValue) % list.Рассчитывать;
Единственная проблема, которая у меня есть, как мне нужно адаптировать IEnumerator, чтобы список оставался списком?

Patrice T

Конечно