字符串的左旋问题解析

来源:互联网 发布:澳洲导航软件 编辑:程序博客网 时间:2024/04/29 18:23

1.实现一个函数,可以左旋字符串中的k个字符。
AABCD左旋一个字符得到ABCDA
AABCD左旋两个字符得到BCDAA

第一种方法:

思路:先将一个字符串左移一位,可以使用一层for循环来实现,
然后每次都可以调用这层循环,调用移位的次数,还有就是,
循环次数如果大于字符串的长度,会重复执行一些无用的
操作,所以给step模上字符串的长度,就可以产生一个小于
字符串长度的数字。

#include<stdio.h>#include<stdlib.h>#include<string.h>#include<assert.h>void str_shift(char *str,int len, int step){    int i = 0;    int j = 0;    char tmp = 0;    step %= len;//step为0到(len - 1)的一个数字,提高了移位时的效率    assert(str);    assert(len > 1);    for (j = 0; j < step; j++)//外层循环实现左移step位    {        tmp = str[0];        for (i = 0; i < len - 1; i++)//内层循环实现了左移一次        {            str[i] = str[i+1];        }        str[i] = tmp;    }}int main(){    char msg[] = "ABCD1234";    int k = 0;    printf("Please Enter:>");    scanf("%d",&k);    printf("before      : %s\n",msg);    str_shift(msg,strlen(msg), k);    printf("shift_after : %s\n",msg);    system("pause");    return 0;}

这里写图片描述

第二种方法:
思路:将一个字符串从它要移位的位置分为两个部分,
(例如:字符串:ABCD1234 要移3位 则将其分为 ABC D1234),
然后将它的左右两边的子字符串各自逆置(CBA 4321D),
然后将逆置后的结果(D1234ABC)再进行整体逆置, 这个结果就是
将原字符串左移3位后的结果。
其实就是将前后两部分各自逆置了两次,然而却把前面的一部分旋转到了这个字符串的尾部。
这里写图片描述

#include<stdio.h>#include<stdlib.h>#include<string.h>#include<assert.h>void swap(char *start, char *end)//交换两个字符{    *start ^= *end;    *end ^= *start;    *start ^= *end;}void reverse(char *start, char *end){    assert(start);    assert(end);    while (start < end)//将字符串逆置    {        swap(start,end);        start++,end--;    }}void str_shift(char *str,int len, int step){    char *middle = NULL;    step %= len;//使得移位的步数小于字符串的长度    middle = str + step - 1;//middle将字符串分为两部分    assert(str);    assert(len > 1);    assert(step > 0);    reverse(str,middle);//将分开的左半部分逆置    reverse(middle +1, str + len - 1);//将分开的右半部分逆置    reverse(str,str + len -1);//将整体逆置}int main(){    char msg[] = "ABCD1234";    int k = 0;    printf("Please Enter:>");    scanf("%d",&k);    printf("before      : %s\n",msg);    str_shift(msg,strlen(msg), k);    printf("shift_after : %s\n",msg);    system("pause");    return 0;}

第三种方法:
思路:使用双重字符串(例如:ABCDABCD),如果需要左旋1位,
则让字符串的首地址加上1,从此处截取字符串长度的字符(BCDA),
则这个结果就是左旋一位后的结果,但是这种方法不适合长度特别大的
字符串。

这里写图片描述

#define _CRT_SECURE_NO_WARNINGS 1#include<stdio.h>#include<stdlib.h>#include<string.h>#include<assert.h>//------双重字符串//1234------1 2341234---左旋一位----(str+1,str+len-1)                     //左旋2位-----(str +2,str+ 2 +len -1)                    // 左旋step位----(str + k,str + step -1)void str_shift(char *str,int len, int step){    char *newstr = NULL;    assert(str);    assert(len > 1);//检查len是否大于1    assert(step > 0 );//检查要左旋的位数是否大于0    step %= len;                   newstr = (char *)malloc(sizeof(char) * len * 2 +1);//开辟双重字符串的空间    strcpy(newstr,str);//将原字符串拷贝到新的字符串中    strcat(newstr,str);//将原字符串连接到新字符串中,使之产生双重字符串    strncpy(str,newstr + step,len);//从左旋的位数开始,复制字符串长度个字符    free(newstr);//在堆上开辟的空间需要自行释放    newstr = NULL;}int main(){    char msg[] = "ABCD1234";    int k = 0;    printf("Please Enter:>");    scanf("%d",&k);    printf("before      : %s\n",msg);    str_shift(msg,strlen(msg), k);    printf("shift_after : %s\n",msg);    system("pause");    return 0;}

这里写图片描述

2.判断一个字符串是否为另外一个字符串旋转之后的字符串。
例如:给定s1 = AABCD和s2 = BCDAA,返回1,给定s1=abcd和s2=ACBD,返回0.

AABCD左旋一个字符得到ABCDA
AABCD左旋两个字符得到BCDAA

AABCD右旋一个字符得到DAABC
AABCD右旋两个字符得到CDAAB

分析:可以在第一道题的思路上向下延伸:
要使得一个字符串是另一个字符串旋转之后得到的字符串,首先
两个字符串长度必须一样长,不然一定不会是旋转之后得到的字符串,
如果一个字符串是另一个字符串经过旋转可以得到的,那么这个字符串
一定是它双重字符串的一个字串。
例如:(ABCD)与(CDAB)——双重字符串(AB**CDAB**CD),
由此可以看出它是它的双重字符串的一个子串。

#define _CRT_SECURE_NO_WARNINGS 1#include<stdio.h>#include<stdlib.h>#include<string.h>#include<assert.h>int  is_sub_str(char *str,char *arr){    char *newstr = NULL;    int len = strlen(str);    assert(str);    assert(arr);    assert(len > 0);//检查len是否大于0    if (strlen(str) == strlen(arr))    {        newstr = (char *)malloc(sizeof(char) * len * 2 +1);//开辟双重字符串的空间        strcpy(newstr,str);//将原字符串拷贝到新的字符串中        strcat(newstr,str);//将原字符串连接到新字符串中,使之产生双重字符串        if (strstr(newstr,arr) == NULL)//如果在双重字符串中没有找到arr这个字符串        {                             //则返回0            return 0;                             }        return 1;//如果在双重字符串中找到了arr字符串,则返回1    free(newstr);//在堆上开辟的空间需要自行释放    newstr = NULL;   }    return 0;}int main(){    char msg[] = "ABCD1234";    char str[] = "CD1234AB";    printf("is sub str : %d",is_sub_str(msg,str));//是---返回1    不是----返回0    system("pause");    return 0;}

这里写图片描述

0 0