美文网首页
旋转字符串

旋转字符串

作者: MinoyJet | 来源:发表于2017-03-20 16:02 被阅读0次

旋转字符串

题目描述:

给定一个字符串,要求把字符串前面的若干个字符移动到字符串的尾部,如把字符串“abcdef”前面的2个字符'a'和'b'移动到字符串的尾部,使得原字符串变成字符串“cdefab”。请写一个函数完成此功能,要求对长度为n的字符串操作的时间复杂度为 O(n),空间复杂度为 O(1)。

分析和解法:

解法一:暴力位移法

首先,我看到题目的第一个想法就是可以通过暴力一位一位的挪移来实现题目要求。
源代码如下:

#include <iostream>
#include <cstring>

using namespace std;
 
void LeftShiftOne(char* s, int n)    //完成当前字符串的第一个字符到尾部 
{
    char t = s[0];   //保存当前字符串的第一个字符 
    for (int i = 1; i < n; i++)
    {
        s[i - 1] = s[i];
    }
    s[n - 1] = t;
}

int main()
{
    char str[100];
    int m; 
    cin.getline(str,100);  //用于输入一行字符串,普通cin最多输入“ abcd”
    cin>>m;
    while(m--)
    {
        LeftShiftOne(str, strlen(str));
    }
    cout<<str<<endl;
    return 0;
}

分析:针对长度为n的字符串来说,假设需要移动m个字符到字符串的尾部,那么总共需要 m*n 次操作,同时设立一个变量保存第一个字符,如此,时间复杂度为O(m * n),空间复杂度为O(1),空间复杂度符合题目要求,但时间复杂度不符合,所以,得需要寻找其他更好的办法来降低时间复杂度。

解法二:三步反转法

(这个方法是我从书上学到的,我一开始也没想到。。。)
将一个字符串分成X和Y两个部分,在每部分字符串上定义反转操作,如XT,即把X的所有字符反转(如,X="abc",那么XT="cba"),那么就得到下面的结论:(XTYT)^T=YX,显然就解决了字符串的反转问题。

例如,字符串 abcdef ,若要让def翻转到abc的前头,只要按照下述3个步骤操作即可:

  • 首先将原字符串分为两个部分,即X:abc,Y:def;
  • 将X反转,X->XT,即得:abc->cba;将Y反转,Y->YT,即得:def->fed。
  • 反转上述步骤得到的结果字符串XTYT,即反转字符串cbafed的两部分(cba和fed)给予反转,cbafed得到defabc,形式化表示为(XTYT)^T=YX,这就实现了整个反转。
    源代码如下:
#include <iostream>
#include <cstring>

using namespace std;
 
void MyReverse(char* s, int from, int to)   //自身反转 
{
    while(from < to)
    {
        char t = s[from];
        s[from++] = s[to];
        s[to--] = t;
    }
}

int main()
{
    char str[100];
    int n,m;
    cin.getline(str, 100);
    cin>>m;
    n = strlen(str);
    MyReverse(str, 0, m-1);
    MyReverse(str, m, n-1);
    MyReverse(str, 0, n-1);
    cout<<str<<endl;
    return 0;
}

分析:这就是把字符串分为两个部分,先各自反转再整体反转的方法,时间复杂度为O(n),空间复杂度为O(1),达到了题目的要求。

特别注意:

  • <string.h>是旧的C 头文件,对应的是基于char*的字符串处理函数,并无类,所以不能 string s1
  • <cstring>是对应于旧C 头文件的std 版本,实际上只是在一个命名空间std中include了 <string.h>
  • <string>是包装了std 的C++头文件,对应的是新的string 类,string s1就是建立一个string类的对象
  • 汉字之所以乱码, 是因为汉字是多字节的, 如果采用单字节翻转,必然就乱码了。你需要判断汉字是几个字节(N), 然后整体翻转移动这N个字节
  • 这里我还想说明一下关于C++输入输出流的问题,有兴趣的可以看一下C/C++输入输出流总结

参考资料:《编程之法》The Art of Programming By July

相关文章

  • 旋转字符串 (lintcode:rotate-string)

    旋转字符串 给定一个字符串和一个偏移量,根据偏移量旋转字符串(从左向右旋转) 例如: 对于字符串 "abcdefg...

  • 旋转字符串

    旋转字符串

  • lintCode题解(8)

    标签(空格分隔): lintCode 旋转字符串 给定一个字符串和一个偏移量,根据偏移量旋转字符串(从左向右旋转)...

  • 判断字符串str1是否是字符串str2的旋转词

    判断字符串str1是否是字符串str2的旋转词 对字符串的旋转操作描述如下:例如: str = "123456" ...

  • 牛客/力扣算法题

    1.逆转字符串 2.旋转字符串

  • LintCode算法刷题之旋转字符串

    链接:旋转字符串 描述 给定一个字符串(以字符数组的形式给出)和一个偏移量,根据偏移量原地旋转字符串(从左向右旋转...

  • LeetCode题解之左旋转字符串

    左旋转字符串 题目描述 字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左...

  • 算法精选题总结之字符串类

    1.字符串旋转2.字符串包含3.字符串的全排列4.字符串转换成整数5.回文判断6.最长回文子串 1.字符串旋转 给...

  • 面试题58 - II. 左旋转字符串

    左旋转字符串 题目描述 字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左...

  • 2020-05-25 第一题

    面试题58 - II. 左旋转字符串 难度简单30 字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部...

网友评论

      本文标题:旋转字符串

      本文链接:https://www.haomeiwen.com/subject/nwujnttx.html