char* reverse(char* s, int n)
{
int i;
char ch;
for (i = 0; i < n / 2; i++) {
ch = s[i];
s[i] = s[n - i -1];
s[n -i - 1] = ch;
}
return s;
}
Well, this might can pass the coding test, for a serious C programmer, I don't think that's the right solution. The problem is as a low level C programmer, you need think like machines, machines do terribly when handling with bytes, but much better with words. Keep this in mind, we could find a much better solution (even it's longer):
static inline void swap64(long long* x, long long* y)
{
long long t = *x;
*x = *y;
*y = t;
}
static inline void swap32(int* x, int* y)
{
int t = *x;
*x = *y;
*y = t;
}
static inline void swap16(short* x, short* y)
{
short t = *x;
*x = *y;
*y = t;
}
static inline void swap8(char* x, char* y)
{
char t = *x;
*x = *y;
*y = t;
}
static inline char* fastrev(char* s, int i, int j)
{
while (i + 16 <= j) {
long long *l1 = (long long*)(s+i);
long long *l2 = (long long*)(s+j-8);
*l1 = bswap_64(*l1);
*l2 = bswap_64(*l2);
swap64(l1, l2);
i += 8;
j -= 8;
}
while(i + 8 <= j) {
int* i1 = (int*)(s+i);
int* i2 = (int*)(s+j-4);
*i1 = bswap_32(*i1);
*i2 = bswap_32(*i2);
swap32(i1, i2);
i += 4;
j -= 4;
}
while(i + 4 <= j) {
short* i1 = (short*)(s+i);
short* i2 = (short*)(s+j-2);
*i1 = bswap_16(*i1);
*i2 = bswap_16(*i2);
swap16(i1, i2);
i += 2;
j -= 2;
}
while (i < j) {
char* c1 = s+i;
char* c2 = s+j-1;
swap8(c1, c2);
i++;
j--;
}
return s;
}
char* reverse(char* s, int n)
{
return fastrev(s, 0, n);
}
(I didn't use swap macro with the well-known `xor` trick, because `xor` on non-words doesn't necessarily faster).
The 2nd solution is 3 times faster on my computer when revering 10^6 bytes string repeated 1000 times (have to do this, otherwise the bottle neck is I/O). Main function:
int main(int argc, char* argv[])
{
char* line;
size_t n;
ssize_t k;
int loop, loopcnt = 1000;
int nt;
scanf("%d\n", &nt);
while(nt--) {
k = getline(&line, &n, stdin);
line[k-1] = '\0';
loop = loopcnt;
while(loop--) {
reverse(line, k-1);
}
printf("%s\n", reverse(line, k-1));
}
free(line);
return 0;
}
{
char* line;
size_t n;
ssize_t k;
int loop, loopcnt = 1000;
int nt;
scanf("%d\n", &nt);
while(nt--) {
k = getline(&line, &n, stdin);
line[k-1] = '\0';
loop = loopcnt;
while(loop--) {
reverse(line, k-1);
}
printf("%s\n", reverse(line, k-1));
}
free(line);
return 0;
}
Timing Result:
[wangbj@nuc tmp]$ ls -l /tmp/i5.txt
-rw-r--r-- 1 wangbj users 1000003 Mar 19 00:43 /tmp/i5.txt
[wangbj@nuc tmp]$ time cat /tmp/i5.txt | ./rev > /dev/null
real 0m0.637s
user 0m0.621s
sys 0m0.015s
[wangbj@nuc tmp]$ time cat /tmp/i5.txt | ./rev2 > /dev/null
real 0m0.206s
user 0m0.197s
sys 0m0.015s
-rw-r--r-- 1 wangbj users 1000003 Mar 19 00:43 /tmp/i5.txt
[wangbj@nuc tmp]$ time cat /tmp/i5.txt | ./rev > /dev/null
real 0m0.637s
user 0m0.621s
sys 0m0.015s
[wangbj@nuc tmp]$ time cat /tmp/i5.txt | ./rev2 > /dev/null
real 0m0.206s
user 0m0.197s
sys 0m0.015s
While there are so much big tech asking algorithm questions (problem is 90% of exactly the same questions can be found online with answers..), reverse a string might not a laughable problem at all!
No comments:
Post a Comment