字符串的旋转

104 阅读2分钟

字符串的旋转

基本旋转

先从左旋讲起,所谓字符串左旋就是将左边的字符移到最右边,然后其余的字符向左移一位
例如: abcdefg 左移一次之后就变为 bcdefga

那么我们就能够依据此定义实现左移的代码:

void left_move(char *arr,int len)
{
    char tmp = *arr;
    for(int i=0;i<len-1;i++)
    {
        *(arr+i) = *(arr+i+1);
    }
    *(arr+i) = tmp;
}

那么如果是移动多次呢, 显然如果每一次都这么移动, 时间效率会比较低

一个算法

有一个实现的方法:

例如我们现在要左移三位

abcdefg --> defgabc

那么我们就将要移至末尾的和无需移至末尾的分为两部分

abc --> cba

defg --> gfed

分别进行逆序

然后合在一起之后再次进行逆序 即为结果

cbagfed --> defgabc

代码实现:

#include <stdio.h>

//指定范围进行逆序
void reverse(char* left,char *right)
{
    while(left<right)
    {
        char tmp = *left;
        *left = *right;
        *right = tmp;
        left++;
        right--;
    }
}

void left_move_k(char *arr,int len,int k)
{
    k = k%len;
    reverse(arr,arr+k-1);
    reverse(arr+k,arr+len-1);
    reverse(arr,arr+len-1);
}

int main()
{
    char arr[] = "abcdefg";
    left_move_k(arr,sizeof(arr)/sizeof(arr[0])-1,3);
    printf("%s",arr);
    return 0;
}

判断是否为某个字符串旋转得来

从0到len-1进行循环 每移动一次就比较一次 如果循环结束之后仍没有匹配的一次结果,那么不是该字符串旋转得来

还有更简单的一个方法 因为左旋旋转的次数如果很大 最终的结果其实也还是0~len-1的旋转 那么旋转的结果一定是比如 abcdefgabcdefg的子串 如果不是子串 那么就不会是该字符串旋转得来

bool is_move_result(char* origin,char* target,int len)
{
    if((sizeof(target)-1)!=len)
    {
        return false;
    }
    char arr[len];
    strcpy(arr,origin);
    strcat(arr,origin);
    return strstr(arr,target)!=NULL;
}

int main()
{
    char arr[] = "abcdefg";
    char target[] = "defgabc";
    if(is_move_result(arr,target,sizeof(arr)-1)){
        printf("是左旋得到的结果");
    }
    else{
        printf("不是左旋得到的结果");
    }
    return 0;
}bool is_move_result(char* origin,char* target,int len)
{
    if((sizeof(target)-1)!=len)
    {
        return false;
    }
    char arr[len];
    strcpy(arr,origin);
    strcat(arr,origin);
    return strstr(arr,target)!=NULL;
}

int main()
{
    char arr[] = "abcdefg";
    char target[] = "defgabc";
    if(is_move_result(arr,target,sizeof(arr)-1)){
        printf("是左旋得到的结果");
    }
    else{
        printf("不是左旋得到的结果");
    }
    return 0;
}