In Column 2 of the book Programming Pearls there is a problem asking you to design an algorithm to rotate a string k positions to the left. For example, the string is "12345" and k=2, then the result is "34512".
The first algorithm is to simulate the exchanging process, i.e. put x[(i + k) % n] into x[i], and repeat until finishing.
The second algorithm uses the observation that we only need to exchange the a="12" and b="345", i.e. first k characters and last n - k characters. We could reverse a to a'="21", and b to b'="543' at first, then reverse (a'b')' to ba, which is desired.
Following is my code:
Algorithm 1:
#define NEXT(j) ((j + k) % n)
#define PREV(j) ((j + n - k) % n)
#include "stdio.h"
#include "stdlib.h"
int gcd(int a, int b) {
return (a % b == 0 ? b : gcd(b, a % b));
}
void solve(int *a, int n, int k) {
int len = gcd(n, k);
for (int i = 0; i < len; i++) {
int x = a[i];
int j = i;
do {
a[j] = a[NEXT(j)];
j = NEXT(j);
} while (j != i);
a[PREV(j)] = x;
}
}
int main(int argc, char const *argv[])
{
int n, k;
scanf("%d %d", &n, &k);
int *a = malloc(sizeof(int) * n);
for (int i = 0; i < n; i++) a[i] = i;
solve(a, n, k);
free(a);
return 0;
}
Algorithm 2:
#include "stdio.h"
#include "stdlib.h"
void swap(int *a, int *b) {
int t = *a;
*a = *b;
*b = t;
}
void reverse(int *a, int n) {
int m = n / 2;
for (int i = 0; i < m; i++) {
swap(a + i, a + (n - 1 - i));
}
}
void solve(int *a, int n, int k) {
reverse(a, k);
reverse(a + k, n - k);
reverse(a, n);
}
int main(int argc, char const *argv[])
{
int n, k;
scanf("%d %d", &n, &k);
int *a = malloc(sizeof(int) * n);
for (int i = 0; i < n; i++) a[i] = i;
solve(a, n, k);
free(a);
return 0;
}
where n is the length of the string, and k is the length to rotate.
I use n=232830359 and k=80829 to test the two algorithms. The result is, algorithm 1 takes 6.199s while algorithm 2 takes 1.970s.
However, I think the two algorithms both need to compute n exchanges. (Algorithm 1 is obvious, algorithm 2 takes k/2 + (n-k)/2 + n/2 = n exchanges).
My question is, why their speeds differ so much?