前言
🎈大家好,我是何小侠🎈
🍃大家可以叫我**小何或者小侠🍃**
💐希望能通过写博客加深自己对于学习内容的理解💐
🌸也能帮助更多人理解和学习🌸
欧阳修《浪淘沙·把酒祝东风》
欧阳修
把酒祝东风, 且共从容。 垂杨紫陌洛城东。 总 是当时携手处,游遍芳丛。
聚散苦匆匆,此恨无穷。今年花胜去年红。 可 惜明年花更好, 知与谁同?
这篇博客我们一起来学习字符串左旋,这也是C语言中比较常见的题目,如果我们能学会今天的方法与思想,基本上你看到这种题目就不再感到棘手,如果说你本来就会那么不妨看看,说不定能让你的思路更加通畅。
左旋字符串题目与思路🍊
话不多说直接看题
这就是我们的思路,将A字符放到字符串最后,然后让A之后的字符串都向前移动。
再细节一点就是利用我们的老办法,创建临时变量当作中转站
代码与细节🍊
void left_rotate(char* arr, int k) { char* left = arr; int len = strlen(arr); char* right = arr + len - 1; while (k % len) { char tmp = *arr; left = arr; while (*left != *right) { *left = *(left + 1); left++; } *left = tmp; k--; } } int main() { char arr[] = "ABCD"; int k = 0; scanf("%d", &k); left_rotate(arr, k); printf("%s", arr); }
我们先要知道一个概念,可以优化我们的代码。
如果我们要左旋4个的字符串就相当于我们不需要旋转,
那么也就是说我们的旋转是有一个周期的,
所以我们计算了strlen(arr)的长度,也就是字符的长度。
那么如果我们需要左旋的数量是k的话,那么在我们left_rotate这个函数最外层while的循环次数也就是k% len。
我们再来看代码,我用tmp作为临时变量永远存着数组第一个字符,
不管字符左旋多少次,我们还是保存着第一个字符。
然后我们*left = *(left + 1)利用这行代码来实现这个过程
但是我们的left不能一直++,我们要在停在最后一个字符上面
*left = tmp;利用这行代码完成这个过程
最后我们的左旋次数减少一次就行
最后也有一个细节,left 的位置还是在最后一个字符上面,所以我们用 left = arr;来让left在需要第二次左旋的时候,再指向第一个字符。
巧解拼接法🍊
我们直接看图
如果我们直接在ABCD这个字符串后面追加一个ABCD,那么我们就可以得到所有的左旋可能,
我们可以想一想,左旋实际上就是1,2,3,4这几种可能。即使推广到更长的字符串也是可以的。
我们给出代码再来讲解
void left_rotate(char* arr, int k) { int len = strlen(arr); k %= len; char tmp[5] = { 0 }; strcpy(tmp, arr + k);//要逆序几个字符串也就是把arr+k放在逆序完的开头 strncat(tmp, arr, k); strcpy(arr, tmp); } int main() { char arr[] = "ABCD"; int k = 0; scanf("%d", &k); left_rotate(arr, k); printf("%s", arr); }
我们创建一个与arr一样大的数组来接收逆序之后的字符串,当然也包括\0。
strcpy(tmp, arr + k);
我们来看这行代码,我们知道strcpy是字符串拷贝,那么也就是说从arr+k到\0,拷贝到tmp,我们用图来看看,假设我们的k是2。
strncat(tmp, arr, k)
再看这行代码,我们知道strncat是字符串追加,那么我们从什么地方开始追加,当然是从开头,为什么呢?我们现在只需要追加k个字符,为什么呢?因为我们需要左旋k个字符。
我们看看图
strcpy(arr, tmp);
最后再把tmp拷贝到arr里面就行了,arr里最终得到的就是左旋后的字符串
更巧妙的逆序法🍊
我在上一篇博客已经介绍了逆序字符串的方法: link
现在我们来看最后一种方法
这种方法就更巧妙了,我们用了更长的字符串更好观察。
void reverse(char* str1, char* str2) { char* left = str1; char* right = str2; while (left < right) { char tmp = 0; tmp = *left; *left = *right; *right = tmp; right--; left++; } } int main() { char arr[] = "ABCDEF"; int k = 0; scanf("%d", &k); int len = strlen(arr); k %= len; reverse(arr, arr + k - 1); reverse(arr + k, arr + len - 1); reverse(arr, arr + len - 1); printf("%s", arr); }
确实是一个很好用的方法,在我看来,我觉得还是逆序还是写起来比较舒服,而常规的左旋考虑的要多一点点。
题目训练🍊
我们可以利用拼接法
int left_rotate(char* arr1, char* arr2) { int len1 = strlen(arr1); int len2 = strlen(arr2); if (len1 != len2) { return 0; } char tmp[11] = { 0 }; strcpy(tmp, arr1); strncat(tmp,arr2 , 5); return strstr(tmp, arr1)!=NULL; // if (ret == NULL) // { // return 0; // } // else // { // return 1; // } //} } int main() { char arr1[] = "AABCD"; char arr2[] = "BCDAA"; int ret = left_rotate(arr1,arr2); if (ret) { printf("YES\n"); } else { printf("NO\n"); } return 0; }
首先判断两个字符串长度是否相等如果不相等就肯定不对
然后还是拼接法的思路只不过多了一个strstr函数来判断是否为子串。
还有就是这个返回值写的也比较简略是比较值得学习的。
总结🍊
这篇博客我介绍了C语言常见的问题——左旋字符串,但是左旋字符串并不代表一定就要左旋,我们也有很多的技巧来判断是否是左旋或者左旋后是怎么样的。
最后如果这篇博客有帮助到你,欢迎点赞关注加收藏
如果本文有任何错误或者有疑点欢迎在评论区评论