This is a classic computer science problem. One technique that's slightly faster is to reverse the entire array, then reverse the two chunks of the array:
// If we want to shift two places, start with an array
[1, 2, 3, 4, 5, 6, 7, 8]
// Then reverse the entire array
[8, 7, 6, 5, 4, 3, 2, 1]
// Then reverse the first n elements, two in our case
[7, 8, 6, 5, 4, 3, 2, 1]
^^^^
// Then reverse the remaining items
[7, 8, 1, 2, 3, 4, 5, 6]
^^^^^^^^^^^^^^^^
Or, as code:
static void Reverse(List<int> items, int posFrom, int posTo)
{
// Helper to reverse a sub portion of an array in place
while (posFrom < posTo)
{
// Swap the first and last items
int temp = items[posFrom];
items[posFrom] = items[posTo];
items[posTo] = temp;
// Shrink down to the next pair of items
--posTo;
++posFrom;
}
}
static void Test8(List<int> items, int places)
{
// Sanity, if we try to rotate more than there are
// items in the array, it just loops around
places %= items.Count;
// Reverse the entire array
Reverse(items, 0, items.Count - 1);
// Reverse the first group of items
Reverse(items, 0, places - 1);
// Reverse the second group of items
Reverse(items, places, items.Count - 1);
}
This is O(n) time, irregardless of the shift size.