patterncppMinor
Rotation of elements in an array
Viewed 0 times
arrayelementsrotation
Problem
We had to write a program that would perform rotation of elements in an array. The array size was entered by user, so it had to be in a sense, dynamic.
Rotation or Circular Shifting
Initial Array:
Shift by:
Final Array:
Notice, in rotation, each elements position increased by shift amount. Also, elements in the end came to the front.
My Try
I used an approach in which I had to create a new array of size = shift amount. This array stored the shift no. of elements in the end of array. Now I shifted all the elements in the beginning of array by shift amount. In the end, I copied the elements of shift sized array to beginning of original array.
I tried to use minimum memory possible so only used shift sized array. I and keep it a bit fast (shift%=n statement to reduce inefficiency if shift >= n).
Question
My question is that all the optimization that i was able to make were a bit obvious and natural. I wanted to know if there was a significant algorithmic, or memory optimization possible for this problem.
PS
I know there's a function
Rotation or Circular Shifting
Initial Array:
1 3 7 4 8 6 5 2 9 Shift by:
4 Final Array:
6 5 2 9 1 3 7 4 8Notice, in rotation, each elements position increased by shift amount. Also, elements in the end came to the front.
My Try
I used an approach in which I had to create a new array of size = shift amount. This array stored the shift no. of elements in the end of array. Now I shifted all the elements in the beginning of array by shift amount. In the end, I copied the elements of shift sized array to beginning of original array.
I tried to use minimum memory possible so only used shift sized array. I and keep it a bit fast (shift%=n statement to reduce inefficiency if shift >= n).
// Rotation
#include
int main() {
int n;
std::cout > n;
int* list = new int[n];
std::cout > list[i];
}
int shift;
std::cout > shift;
shift %= n; // to reduce work if shift > n
int* temp = new int[shift];
for( int i = n-shift; i = shift; --i) {
list[i] = list[i-shift];
}
for( int i = 0; i < shift; ++i) {
list[i] = temp[i];
}
delete [] temp;
// Printing
for( int i = 0; i < n; ++i) {
std::cout << list[i] << " ";
}
delete [] list;
}Question
My question is that all the optimization that i was able to make were a bit obvious and natural. I wanted to know if there was a significant algorithmic, or memory optimization possible for this problem.
PS
I know there's a function
std::rotate available from algorithm, but we had to solve this problem on our own.Solution
I see some things that may help you improve your program.
Separate I/O from calculations
The program has three basic phases. First, it gets input, then it manipulates that input, and then it produces output. I would recommend putting the rotation code into a separate function.
Consider signed vs. unsigned
Does it make sense to have a negative array size? Does it make sense to have a negative shift value? I'd answer "no" to the first and "yes" to the second question. For that reason, I'd recommend making
Rethink your algorithm
The code currently creates a temporary array, but all that's really needed is a single temporary
Worked example
This is probably easier to understand with an example. Let's start with a simple array or length 7 =
Separate I/O from calculations
The program has three basic phases. First, it gets input, then it manipulates that input, and then it produces output. I would recommend putting the rotation code into a separate function.
Consider signed vs. unsigned
Does it make sense to have a negative array size? Does it make sense to have a negative shift value? I'd answer "no" to the first and "yes" to the second question. For that reason, I'd recommend making
n a size_t or unsigned type and also adding code to handle negative rotations.Rethink your algorithm
The code currently creates a temporary array, but all that's really needed is a single temporary
int. Here's one way to do it:unsigned gcd(unsigned a, unsigned b) {
return b == 0 ? a : gcd(b, a % b);
}
void rotate(unsigned n, int shift, int *list)
{
if (shift = n) {
nexti -= n;
}
std::swap(temp, list[i+cycles-1]);
}
}
}Worked example
This is probably easier to understand with an example. Let's start with a simple array or length 7 =
{ 0, 1, 2, 3, 4, 5, 6} and a requested shift amount of 4. When the for loop starts we have this:Code Snippets
unsigned gcd(unsigned a, unsigned b) {
return b == 0 ? a : gcd(b, a % b);
}
void rotate(unsigned n, int shift, int *list)
{
if (shift < 0) {
shift = n -(-shift % n);
} else {
shift %= n;
}
if (shift == 0) {
return;
}
for (unsigned cycles = gcd(n, shift); cycles; --cycles) {
unsigned i = 0;
unsigned nexti = n-shift;
for (int temp=list[nexti+cycles-1]; nexti; i = nexti) {
nexti = i+shift;
if (nexti >= n) {
nexti -= n;
}
std::swap(temp, list[i+cycles-1]);
}
}
}Context
StackExchange Code Review Q#122146, answer score: 7
Revisions (0)
No revisions yet.