题目描述:
实现一个函数,可以左旋字符串中的k个字符。
例如:
ABCD左旋一个字符得到BCDA
ABCD左旋两个字符得到CDAB
问题解决:
假设字符串为"abcdef",要注意其实为"abcdef\0",我们可以将这个问题转换为n次的移动。首先,将第一个字符保存起来(a),然后求一下字符串的长度(6),然后从第二个字符开始到最后一个字符,依次去覆盖前一个字符。也就是说,通过循环(字符串长度减一次),将i位置的字符放在i+1的位置上。最后,将一开始保存的第一个字符直接放在最后一个字符的位置处,完成一次左移操作。通过最外层的循环来循环k次实现k次左移的循环操作。
#include <stdio.h>
#include <assert.h>void left_move(char* str, int k)
{int j = 0;assert(str);//不可以为空字符串for (j = 0; j < k; j++){//abcdef\0char tmp = *str;//先将a储存起来int len = strlen(str);//求一下字符串的长度int i = 0;for (i = 0; i < len - 1; i++){//长度为6,移到5次//从b开始到f依次移到前一个位置*(str + i) = *(str + i + 1);}//最后一个位置把刚刚保存的a放进去*(str + len - 1) = tmp;//循环k次表示移动k次}
}int main()
{char arr[] = "abcdef";int k = 0;scanf_s("%d", &k);left_move(arr, k);printf("%s\n", arr);return 0;
}
设计循环使其可以旋1次,然后让他执行n次是一个最简单的思路:
void leftRound(char * src, int time)
{int i, j, tmp;int len = strlen(src);time %= len; //长度为5的情况下,旋转6、11、16...次相当于1次,7、12、17...次相当于2次,以此类推。for (i = 0; i < time; i++) //执行k次的单次平移{tmp = src[0];for(j = 0; j < len - 1; j++) //单次平移{src[j] = src[j + 1];}src[j] = tmp;}
}
还可以使用另一种方法:三次reverse
#include <stdio.h>
#include <assert.h>
void reverse(char* left, char* right)
{assert(left && right);while (left<right){char tmp = *left;*left = *right;*right = tmp;left++;right--;}
}void left_move(char* str, int k)
{int len = strlen(str);k %= len;//避免重复操作//左边逆序reverse(str, str+k-1);//右边逆序reverse(str+k, str + len - 1);//整体逆序reverse(str, str + len-1);
}int main()
{char arr[] = "abcdef";//bafedc//cdefabint k = 0;scanf_s("%d", &k);//10%6=4left_move(arr, k);printf("%s\n", arr);return 0;
}
void reverse_part(char *str, int start, int end) //将字符串从start到end这一段逆序
{int i, j;char tmp;for (i = start, j = end; i < j; i++, j--){tmp = str[i];str[i] = str[j];str[j] = tmp;}
}void leftRound(char * src, int time)
{int len = strlen(src);int pos = time % len;reverse_part(src, 0, pos - 1); //逆序前段reverse_part(src, pos, len - 1); //逆序后段reverse_part(src, 0, len - 1); //整体逆序
}
当然,还有一种解法:
#include <stdio.h>
//#include <string.h>
#include<ctype.h>
void leftRound(char* src, int time)
{int len = strlen(src);int pos = time % len; //断开位置的下标char tmp[256] = { 0 }; //更准确的话可以选择malloc len + 1个字节的空间来做这个tmpstrcpy(tmp, src + pos); //先将后面的全部拷过来strncat(tmp, src, pos); //然后将前面几个接上strcpy(src, tmp); //最后拷回去
}
int main()
{char arr[] = "abcdef";int k = 0;scanf_s("%d", &k);leftRound(arr, k);printf("%s\n", arr);return 0;
}