How do you efficiently right-shift an array with the least memory usage?
For example, the original array could be 2 3 4 5 6. after right-shift two positions, it should be 5 6 2 3 4. The function prototype is shift_right (int[] arret, int shiftCount).
OR
Algorithm to right-shift an array M places, where M < length(array)
Solution 1:
Here is the exact solution as given in “Programming Pearls, 2nd Edition” :
“Swap all the numbers M times”
For example: Say you have an array[1,2,3,4] and you have to shift
it right 2 places. The
--- Start ---
[1,2,3,4]
--- First Pass ---
[1,2,3,4]
^ ^
[2,1,3,4]
^ ^
[2,3,1,4]
^ ^
[2,3,4,1]
--- Second Pass ---
[2,3,4,1]
^ ^
[3,2,4,1]
^ ^
[3,4,2,1]
^ ^
[3,4,1,2]
--- Result ---
[3,4,1,2]
Complexity:
Not good! Take the worstcase. Say you have an array of length `n` and you have to shift all elements `n-1` places.
The complexity becomes `O(N*(N-1)) ≈ O(N^2)` as `n -> ∞`.
In average case it will be O(mN), where `m` is the number of places to shift.
Solution 2:
Yet another solution.
Step 1: reverse the array by swapping all the elements (single pass, O(N))
Step 2: reverse all the elements from 0 to `M-1`
Step 3: reverse all the elements from `M` to `L-1` (where L is the length of the array)
Array : [1,2,3,4,5], M=3
First pass : [5,4,3,2,1] (all elements swapped reversing the array)
Second pass : [3,4,5,2,1] (reverse array from 0 to 3-1=2)
^ ^ ^
Third Pass : [3,4,5,1,2] (reverse elements 3 to 5)
^ ^
Result : [4,5,1,2,3]
As simple as that !!
Java Code: [ source: sun java fourums ]
int[] reverse(int[] a, int i, int j) { // reverse elements i, i+1 ... j-1
for (; --j > i; i++) {
int t= a[i]; a[i]= a[j]; a[j]= t;
}
return a; // convenience.
}
int[] shiftRight(int[] a, int i) {
return reverse(reverse(reverse(a, 0, a.length), 0, i), i, a.length);
}
Complexity: O(N)
Basically you traverse over the array twice, hence the complexity turns out to be O(2N) ≈ O(N)` as `n -> ∞`.