c语言左旋字符串中的k个字符

实现一个函数,可以左旋字符串中的k个字符。
ABCD左旋一个字符得到BCDA
ABCD左旋两个字符得到CDAB

由上面的例子我们可以明白旋转的含义,所以下面直接给出三种接法。


方法一:
可以使用循环移位法,比如说字符串ABCD,左旋一次,得到BCDA。
可以先将A取出放在一个临时变量中,然后将后面的字符依次前移一位。此时最后一位就空出来了, 再将第一次放入临时变量中的A放入最后一位。左旋几个字符,重复几次上述步骤即可。
但要注意一个问题,对于ABCD这个字符串来说,左旋4次实际上就回到了它本来的顺序,所以左旋大于4以上的次数都是多余的动作,所以在左旋之前需要先去除冗余动作。
附上代码:

void left_shift(char *str,int len,int step)
{
    assert(str);
    step %= len;
    char tmp = 0;
    int i = 0;
    while (step--)
    {   tmp = str[0];
        for (i = 0; i < len - 1; i++)
        {
            str[i] = str[i + 1];
        }
        str[len - 1] = tmp;
    }
}

这里写图片描述

这里写图片描述


方法二:
逆置字符串法。
首先先看一个例子。ABCD 1234
如果我们对这个字符串左旋4次。以第四个字符为界限,将该字符串分成两部分,然后分别逆置。得到DCBA 4321。最后对这个字符串整体逆置。就得到1234ABCD。
代码如下:

void reverse_str(char *start, char * end)
{
    assert(start);
    assert(end);
    while (start<end)
    {
        *start ^= *end;
        *end ^= *start;
        *start ^= *end;
        start++;
        end--;
    }
}
void left_shift(char *str, int len, int step)
{
    assert(str);
    step %= len;
    char *start = str;
    char *end = str + len - 1;
    char *middle = start + step - 1;
    reverse_str(start, middle);
    reverse_str(middle+1, end);
    reverse_str(start, end);

}

方法三:双倍字符串法。
比如说还是ABCD1234这个字符串。
ABCD1234—–>ABCD1234ABCD1234
这个扩充后的字符串穷举了所有左旋了之后的可能性。
假如我们对它左旋4次,在新的字符串中找到第四个元素(不包括),依次读取后面的8个即是结果。

//方法三:双倍字符串法
void left_shift(char *str, int len, int step)
{
    assert(str);
    step %= len;
    char *buff = (char *)malloc(2 * len + 1);
    strcpy(buff, str);
    strcat(buff, str);
    strncpy(str, buff + step, len);
    free(buff);
    buff = NULL;
}

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

最简单的方法是利用循环移位法,每旋转一次判断一次。在这里提出一种更简单的方法。当我们理解了上面的双倍字符串法,可以考虑如果一个字符串是扩充后的双倍字符串的子串的话,那么它一定是原字符串左旋得来的。前提是判断的字符串要与原字符串长度相等。

int left_shift(char *str, char *arr)
{
    assert(str);
    assert(arr);
    int len = strlen(str);
    char *buff = (char *)malloc(2 * len + 1);
    if (strlen(arr) != len)
    {
        return 0;
    }
    strcpy(buff, str);
    strcat(buff, str);
    if (strstr(buff, arr) != NULL)
    {
        return 1;
    }
    else
    {
        return -1;
    }
    free(buff);
    buff = NULL;
}

int main()
{
    char str[] = "ABCD";
    char arr[] = "BCDA";
    int ret=left_shift(str,arr);
    printf("%d\n", ret);
    if (ret == 1)
    {
        printf("yes");
    }
    else
    {
        printf("no");
    }
    system("pause");
    return 0;

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值