How can I write a function shift(int* arr, int k) cyclically shift an array by some integer k? I cannot say “malloc” memory from the heap.
For instance, using pseudocode, shift([1, 2, 3, 4], 2) returns [3, 4, 1, 2], and shift([3, 1, 5, 5], 103) returns [1, 5, 5, 3]. I have tried using modulus to achieve this effect, as shown in this Java program, in which I basically iterate through half of the array and swap values.
public static int* shift(int* arr, int k) {
int half_array_len = arr.length / 2;
for (int i = 0; i < half_array_len; ++i) {
// Swap!
int newIndex = (i + k) % arr.length;
int temp = arr[i];
arr[i] = arr[newIndex];
arr[newIndex] = arr[i];
}
return arr;
}
However, I believe that this function only works for even-lengthed arrays.
How can I implement shift for arrays of any length? Answers can be in any language you want (Java, C++, Ook Ook!, etc.).
(Has been asked several times before.) Basically, three classic in-place algorithms dedicated to solving this problem are described and analyzed in Bentley’s “Programming Pearls” (Juggling, Reversal and Block Swap algorithms). These slides describe them in sufficient detail
http://www.cs.bell-labs.com/cm/cs/pearls/s02b.pdf
The simplest algorithm is the Reversal Algorithm. Simply reverse the entire array and then reverse each [n – k] and [k] block independently. Done. (From which end the [k] block is counted depends on the direction of the shift.)
Of course, it makes sense to normalize the
kfirst, i.e, dok = k % nto make surekis less thann.P.S. In C++ the answer would be to use
std::rotate, which does exactly what you want. But I doubt this is the answer you seek. Although you might want to take a look at some implementations ofstd::rotate(if only to discover that they typically use the Reversal algorithm 🙂