What is the fastest algorithm for circle shifting array for M positions?
For example, [3 4 5 2 3 1 4]
shift M = 2 positions should be [1 4 3 4 5 2 3]
.
Thanks a lot.
What is the fastest algorithm for circle shifting array for M positions?
For example, [3 4 5 2 3 1 4]
shift M = 2 positions should be [1 4 3 4 5 2 3]
.
Thanks a lot.
A friend of mine while joking asked me how to shift an array, I came up with this solutions (see ideone link), now I've seen yours, someone seems a bit esoteric.
Take a look here.
Here is my solution in Java which got me 100% Task Score and 100% Correctness at Codility:
Note that despite seeing two
for
loops, the iteration on the entire array is only done once.Optimal solution
Question asked for fastest. Reversing three times is simplest but moves every element exactly twice, takes O(N) time and O(1) space. It is possible to circle shift an array moving each element exactly once also in O(N) time and O(1) space.
Idea
We can circle shift an array of length
N=9
byM=1
with one cycle:And if
N=9
,M=3
we can circle shift with three cycles:tmp = arr[0]; arr[0] = arr[3]; arr[3] = tmp;
tmp = arr[1]; arr[1] = arr[4]; arr[4] = tmp;
tmp = arr[2]; arr[2] = arr[5]; arr[5] = tmp;
Note each element is read once and written once.
Diagram of shifting
N=9, M=3
The first cycle is show in black with numbers indicating the order of operations. The second and third cycles are shown in grey.
The number of cycles required is the Greatest Common Divisor (GCD) of
N
andM
. If the GCD is 3, we start a cycle at each of{0,1,2}
. Calculating the GCD is fast with the binary GCD algorithm.Example code:
Code in C for any array type:
Edit: This algorithm may also have better performance vs array reversal (when
N
is large andM
is small) due to cache locality, since we are looping over the array in small steps.Final note: if your array is small, triple reverse is simple. If you have a large array, it is worth the overhead of working out the GCD to reduce the number of moves by a factor of 2. Ref: http://www.geeksforgeeks.org/array-rotation/
Here is a nother one (C++):
Of course it is not nearly as elegant as the famous reverse-three-times solution, but depending on the machine it can be similary fast.
It's just a matter of representation. Keep the current index as an integer variable and when traversing the array use modulo operator to know when to wrap around. Shifting is then only changing the value of the current index, wrapping it around the size of the array. This is of course O(1).
For example:
This code works well even on negative shift k