一個長度為len的字符串,對其循環右移n位
[期望]
char str[] = "abcdefg";
右移3次后,變成"efgabcd"
[思路]
思路1.
如果用每移動一次,就要把整個字符串整體移動一次的方法,顯得太費勁了。
我們可以用空間換時間,通過內存拷貝來實現。
需要新申請一塊相同大小的內存,把原字符串的后n個字節拷貝到它的開始地址,把原字符串的前(len-n)個字節拷貝到它的(開始地址+n)處。
為便於查看結果,我們先定義一個打印字符串的函數void print_str(char *str);
void print_str(char *str) { int i,len; if (str == NULL) { return; } len = strlen(str); for(i=0; i<len; i++) { printf("%c",str[i]); } printf("\n"); }
思路1的代碼實現:
#include <stdio.h> #include <string.h> #include <stdlib.h> void print_str(char *str) { int i,len; if (str == NULL) { return; } len = strlen(str); for(i=0; i<len; i++) { printf("%c",str[i]); } printf("\n"); } int str_rshift_1(char *str, int n) { int len; char *tmp; len = strlen(str); if (len < n) { return 1; } tmp = (char *)malloc(len); if (tmp == NULL) { return 1; } memcpy(tmp, str+len-n, n); memcpy(tmp+n, str, len-n); memcpy(str, tmp, len); free(tmp); str[len] = '\0'; return 0; } void str_rshift_1_test() { char str[] = "abcdefg"; str_rshift_1(str, 3); print_str(str); } void main() { str_rshift_1_test(); }
思路2.
來自《編程珠璣》里的算法,利用字符串的逆序來實現。
比如字符串"abcdefg",要循環右移3位,那么這個字符串可以分為2部分:
前半部分:"abcd" 和后半部分 "efg"。
我們先把前半部分逆序變成 -> "dcba"
再把后半部分逆序變成-> "gfe"
這時整體字符串應該是 "dcbagfe"
我們再對整個字符串逆序一遍,結果-> "efgabcd"。
bingo,循環右移完成。
總結一下,總共要進行3次逆序:前半部分逆序,后半部分逆序,整體逆序。
逆序用到的函數原型是void str_reverse(char *str, int left, int right);它的實現在這里。
思路2的代碼實現:
int str_rshift_2(char *str, int n) { int len = strlen(str); if (len < n) { return 1; } str_reverse(str, 0, len-n-1); str_reverse(str, len-n, len-1); str_reverse(str, 0, len-1); return 0; } void str_rshift_2_test() { char str[] = "abcdefg"; str_rshift_2(str, 3); print_str(str); } void main() { str_rshift_2_test(); }
