C语言——字符串旋转问题

字符串的旋转:
ABCD左旋一个字符为BCDA
ABCD左旋两个字符为CDAB
ABCD右旋一个字符为DABC
ABCD右旋两个字符为CDAB
这里只写了左旋,右旋的原理和左旋一样 。
目录
实现旋转字符串:
1、暴力求解法:
2、三步翻转法
判断一个字符串是否由另一个字符串旋转而来
1、暴力求解法:
2、优化算法:
关于用到的函数扩展:
1、(断言函数)
2、(字符串比较函数)
3、(字符串追加函数)
4、(字符串追加函数)
5、(判断是否子串函数)
实现旋转字符串: 1、暴力求解法:
思路:
假如只旋转一个字符:
将第一个字符从字符串中 拿 出来,然后将后面的字符依次向前移动,最后再将 拿 出来的第一个字符串放到最后面;
要旋转k个字符的话,只需用一个循环,以循环变量小于k作为循环条件即可 。
代码及详情如下:
#include//1、暴力求解法:void left_move(char* arr, int k) {int len = strlen(arr);assert(arr);//断言函数assert(k < len&& k >= 0);//将旋转的第一个字符先存起来,然后将这个字符的后面的字符依次往前移,然后再把旋转的字符放在最后for (int i = 0; i < k; i++) {//旋转几次就循环几次char tmp = arr[0];//*arrfor (int j = 0; j < len-1; j++) {arr[j] = arr[j + 1];//*(arr+j)=*(arr+j+1);}arr[len - 1] = tmp;//最后将拿出来的字符放进最后一个位置}}
2、三步翻转法
思路:
将一个字符串分成两部分:
1.要旋转的部分
2.不旋转的部分
先将要旋转的部分给他逆序,然后再将不旋转的部分给他逆序,最后所有该字符串逆序 。
比如:
要旋转两个字符--> ab cdef
1.先将旋转部分ab逆序-->ba cdef
2.再将不旋转部分逆序-->ba fedc
3.最后全部逆序-->
此时得到了旋转后的结果
代码及详情如下:
//逆序函数//使用头尾双指针来实现void inversion(char* left, char* right) {assert(left);assert(right);while (left < right) {char tmp = *left;*left = *right;*right = tmp;left++;right--;}}//三步翻转法void left_move(char* arr,int k) {assert(arr);int len = strlen(arr);//字符串长度,用来方便求尾指针//用头尾指针来进行逆序//1、要旋转部分的逆序inversion(arr, arr + k - 1);//arr是头地址,arr+k-1是这部分的尾地址//2、不旋转部分的逆序inversion(arr + k, arr + len - 1);//3、全部部分的逆序inversion(arr, arr + len - 1);}
判断一个字符串是否由另一个字符串旋转而来
如:bcdea 是由 abcde 旋转一个字符得到的 。
1、暴力求解法:
思路:
arr1与arr2:
用arr1 的所有旋转情况来和arr2 比较,如果其中有一种情况和arr2 相同,说明arr2 就是由arr1 旋转得到的 。
假如arr1=“abcd”,他的所有旋转情况:
1、bcda;2、cdab;3、dabc;4、abcd 。
arr2 只要和其中一种情况符合就是由arr1 旋转而来的 。
代码及详情如下:
//1、暴力求解法/*将原字符串所有的旋转可能都拿出来与另一字符串比较,若有相同的则yes*/int is_left_move(char* arr1, char* arr2) {int len = strlen(arr1);//用来作循环条件,因为最多要将每一个字符都旋转一次for (int i = 0; i < len; i++) {left_move(arr1, 1);//这里的数字代表旋转字符的个数因为是一个一个字符旋转,所以这里旋转个数只能写1,如果写了2,那么第一次就会旋转2字符然后会一直都旋转两字符if (strcmp(arr1, arr2) == 0)//每旋转完一个字符就比较两字符串return 1;}return 0;}
2、优化算法:
思路:
将arr1 复制份然后加在原arr1 的后面,此时的新arr1 包含了旋转的所有情况,然后用双指针来与arr2 进行比较 。