I'm trying to rotate an array such that given a number and an array, rotate the array by that amount. IE:
abcdefgh
given 3:
fghabcde
What is the best way to do this without using additional data structures/minimal space?
Here is a function header:
public static char[] rotateString(char[] s, int rotateAmount){
}
The Java implementation of Collections.rotate(List, int)
can be found here; it uses only constant overhead, and it's quite clean and easy to understand. I wouldn't necessarily just call it (although with a wrapper like Guava's Chars.asList
, there would only be a constant overhead), but the algorithm is neat and clean, and you could adapt it easily enough to your needs.
It's O(n)
, but the reason why isn't quite obvious; most of the work is figuring out why it will never visit any one index more than once. I'll leave that as an exercise.
Firstly, I will make a big assumption that "better" means "I do not want any/as few new data structures".
If this is the case, then the simplest solution is the best, since I don't need to bother optimising by time. I know that the other solutions are much more elegant, I've only posted it because I've read the question as "make sure it's minimal space-wise".
private static String rotate( final char[] a, final int n ) {
for(int i = 0; i < n; i++) {
char tmp = a[a.length-1];
for(int j = a.length-1; j >= 0; j--) {
a[j] = j == 0 ? tmp : a[(j-1+a.length)%a.length];
}
}
return new String(a);
}
So I hacked this out pretty quickly. Basically, I'm just doing rotates by lengths of one until I've rotated n
number of times. To optimise it you probably could take gcd(n, a.length)
.
Now, since my solution is pretty terrible, I'll also post the following code taken from here
void reverse_string(char* str, int left, int right) {
char* p1 = str + left;
char* p2 = str + right;
while (p1 < p2) {
char temp = *p1;
*p1 = *p2;
*p2 = temp;
p1++;
p2--;
}
}
void rotate(char* str, int k) {
int n = strlen(str);
reverse_string(str, 0, n-1);
reverse_string(str, 0, k-1);
reverse_string(str, k, n-1);
}
This is, what I assume to be a C-style implementation that runs faster than mine, using a basic idea that with three reverses, you can implement an inline shift.
As is said here,
The trick is to do three reverse operation. One for the entire string, one from index 0 to k-1, and lastly index k to n-1. Magically, this will yield the correct rotated array, without any extra space! (Of course, you need a temporary variable for swapping).
I haven't verified this property on the blog I've linked to, so I will post it with a grain of salt that it would appear to work but I've never tested it myself...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With