Reputation: 2009
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){
}
Upvotes: 4
Views: 8437
Reputation: 1120
Try this :
public static char[] rotateString(char[] s, int rotateAmount){
String oldStr=new String(s);
String newStr=oldStr.substring(oldStr.length()-rotateAmount,oldStr.length())+oldStr.substring(0,oldStr.length()-rotateAmount);
return newStr.toCharArray();
}
Upvotes: -1
Reputation: 1
I think this is simplier and definitely faster
private static String rotate( char[] arrayStr, int K, int N ) {
int[] my_array = new int[N];
for(int item = 0; item < N; item++) {
my_array[(item+K) % N] = arrayStr[item];
}
return my_array
}
where K = number of rotation and N = lenght of array
Upvotes: 0
Reputation: 3451
Here is c# version of it just for reference (you may refer to:http://codingworkout.blogspot.com/2014/07/rotating-array.html for more details):
void swap<T>(ref T x, ref T y)
{
T t = x;
x = y;
y = t;
}
void Reverse(int[] a, int start, int end)
{
int i = start, j = end;
while (i < j)
{
swap<int>(ref a[i], ref a[j]);
i++;
j--;
}
}
void Rotate(int[] a, int k)
{
a.ThrowIfNull("array");
k.Throw("k", e => e < 0);
if (a.Length <= 1)
{
return;
}
k = k % a.Length;
this.Reverse(a, 0, a.Length - 1);
this.Reverse(a, 0, k - 1);
this.Reverse(a, k, a.Length - 1);
}
Unit Tests
[TestMethod]
public void RotateTests()
{
int[] a = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
for (int i = 1; i <= a.Length; i++)
{
int k = a.Length - i + 1;
int[] b = new int[a.Length];
this.Rotate(a, i);
for(int j = 0;j<b.Length;j++)
{
if(k > a.Length)
{
k = (k % a.Length);
}
b[j] = k;
k++;
}
for (int j = 0; j < a.Length;j++ )
{
Assert.IsTrue(a[j] == b[j]);
}
this.Rotate(a, a.Length - i);
}
}
Upvotes: 0
Reputation: 24484
The function should work in both directions and when there is one or more turnarounds - as turning by number more than the length of the array.
public static char[] rotateString(char[] s, int rotateAmount){
int n=s.length;
char[] res=new char[n];
if (n==0) return res;
int turns=rotateAmount / n;
int j=((-turns+1)*n+rotateAmount) % n;
for (int i=0; i<n; i++){
if(j==n) j=0;
res[j]=s[i];
j++;
}
return res;
}
tested by:
System.out.println("'',+1->"+new String(rotateString("".toCharArray(),+1)));
System.out.println("123,+1->"+new String(rotateString("123".toCharArray(),+1)));
System.out.println("123,-1->"+new String(rotateString("123".toCharArray(),-1)));
System.out.println("123,-5->"+new String(rotateString("123".toCharArray(),-5)));
System.out.println("123,-6->"+new String(rotateString("123".toCharArray(),-6)));
System.out.println("123,+6->"+new String(rotateString("123".toCharArray(),+6)));
Upvotes: 1
Reputation: 15725
Something like this ?
It requires O(1) extra storage for temp
.
Try running this with shift=1
, to see the idea behind it.
public static String rotateString(char[] s, int rotateAmount) {
int length = s.length;
int shift = (length - rotateAmount) % length;
for (int start = 0; start < gcd(length, shift); start++) {
char temp = s[start];
for (int i = (start + shift)%length; i != start; i = (i + shift) % length) {
s[(length + i - shift) % length] = s[i];
}
s[(length + start - shift) % length] = temp;
}
return new String(s);
}
gcd(a,b)
is the greatest common denominator of a
and b
, and can be computed using e.g., Euclid's Algorithm.
The time complexity is O(n), where n
is the length of the array.
Upvotes: 1
Reputation: 198491
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.
Upvotes: 3
Reputation: 7334
How about using Stack?
Let me explain. When you push abcdefgh to stack it becomes hgfedcba
Now Pop one element at a time and prepend the string. lets assume rotation amount is 3.
When you pop first elemnt you get h. Since 3 is less than number of characters popped pop one more element and prepend to h. So when you pop the next element you get g. Prepend g to h. So it becomes hg. Repeat the process for the amount of rotation(here it is 3) hence it becomes fgh.
Now Create a new string and pop the rest of elements from the stack and prepend each character popped. Hence it becomes "abcd".
Combine the two strings. which is fghabcd.
Upvotes: 0
Reputation: 1314
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...
Upvotes: 6