剑指Offer详解之左旋转字符串

简介:

(1)暴力移位法

这种方法可能是最直观,最容易想出的方法。但这也是最坏的方法。时间复杂度挺高,用这种方法容易超时。
这种方法是一位一位的移动实现左旋转操作。
【代码】
#include <stdio.h>
#include <malloc.h>
#include <string.h>

char *str;

char* Reverse(char* str,int n){
    if(str == NULL || n < 0){
        return "";
    }
    int len = strlen(str);
    int i;
    char temp;
    //循环左移n位
    while(n--){
        //左移
        //保存第一个字符
        temp = str[0];
        for(i = 1;i < len;i++){
            str[i-1] = str[i];
        }
        str[len-1] = temp;
    }
    return str;
}


int main() {
    int i,n;
    str = (char*)malloc(sizeof(char)*1001);
    while(scanf("%s",str) != EOF){
        scanf("%d",&n);
        //左旋转
        str = Reverse(str,n);
        //输出
        for(i = 0;i < strlen(str);i++){
            printf("%c",str[i]);
        }
        printf("\n");
    }//while
    return 0;
}

对上述的方法进行进一步的优化。
UDBOJ 4
对上述字符串循环左移4次,8次,12次。。。。。(n % len )效果是一样的
左移次数:n % len                n原始左移次数   len字符串长度

【代码】
char* Reverse(char* str,int n){
    if(str == NULL || n < 0){
        return "";
    }
    int len = strlen(str);
    int i;
    char temp;
    //对左移次数进行优化
    n = n % len;
    //循环左移n位
    while(n--){
        //左移
        //保存第一个字符
        temp = str[0];
        for(i = 1;i < len;i++){
            str[i-1] = str[i];
        }
        str[len-1] = temp;
    }
    return str;
}

(2)指针翻转法

 咱们先来看个例子,如下:
 abcdefghi,若要让abc移动至最后的过程可以是:
abc defghi->def abc ghi->defghi abc

如此,我们可定义俩指针,p1指向ch[0],p2指向ch[m];
一下过程循环m次,交换p1和p2所指元素,然后p1++, p2++;。

第一步,交换abc 和def ,
abc defghi->def abc ghi
第二步,交换abc 和ghi,def
abc ghi->defghi abc

整个过程,看起来,就是abc作为一组一步一步向后移动

abcdefghi
defabcghi
defghiabc  
//最后的 复杂度是O(m+n) 

由上述例子九个元素的序列abcdefghi,您已经看到,m=3时,p2恰好指到了数组最后一个元素,每m个一组正好一一对应。于是,上述思路没有问题。但是每m个一组有剩余时怎么办?假设abcde,还能如上面的方法解决吗?这样就不可以了,那样就数组越界了。所以我们要特殊处理尾部不够m个一组的元素。
就举这个例子,对abcdefghij序列进行左旋转操作:

如果abcdefghij要变成defghijabc:
1. def
abc ghij
2. defghi
abc j      //最后一个j不够一组m个要单独处理
3. defghi
ab j c      //我们需要一次一次交换移至前面
4. defghi
a j bc
5. defghijabc 

下面,再针对上述过程,画个图清晰说明下,如下所示:


总结:
1、首先让p1=ch[0],p2=ch[m],即让p1,p2相隔m的距离,可以理解为每m个一组,第一组和后每组对应交换;
2、判断p2+m-1是否越界,即判断最后一组是不是构成一组。如果不能构成一组就不能一一对应交换,如果没有越界转到3,否则转到4。
3、不断交换*p1与*p2,然后p1++,p2++,循环m次,然后转到2。
4、此时p2+m-1已经越界,即最后一组不能构成一组,不能一一对应交换,需处理尾巴。
过程如下:
   4.1 通过n-p2得到p2与尾部之间元素个数r,即我们要前移的元素个数。
   4.2 以下过程执行r次:
       ch[p2]<->ch[p2-1],ch[p2-1]<->ch[p2-2],....,ch[p1+1]<->ch[p1];p1++;p2++;
所以,之前最初的那个左旋转九个元素abcdefghi的思路在末尾会出现问题的(如果p2后面有元素就不能这么变,例如,如果是处理十个元素,abcdefghij?对的,就是这个意思),解决方法:
def ghi abc jk
当p1指向a,p2指向j时,由于p2+m越界,那么此时p1,p2不要变
这里p1之后(abcjk)就是尾巴,处理尾巴只需将j,k移到abc之前,得到最终序列,代码编写如下:

#include <stdio.h>
#include <malloc.h>
#include <string.h>

char *str;

void Reverse(char* str,int n){
    if(str == NULL || n <= 0){
        return;
    }
    int len = strlen(str);
    int pre = 0;
    int p = n;
    char temp;
    //len % n  n个一组,不够一组的个数
    //len - n - len % n  表示总个数减去最前一组减去最后不够一组的个数
    //交换次数
    int count = len - n - len % n;
    while(count--){
        //交换
        temp = str[pre];
        str[pre] = str[p];
        str[p] = temp;
        pre++;
        p++;
    }
    //处理最后尾部不够一组的元素
    //rear为尾部左移元素个数
    int rear = len - p;
    while(rear--){
        //左移
        int i = p;
        while(i > pre){
            temp = str[i];
            str[i] = str[i-1];
            str[i-1] = temp;
            i--;
        }
        p++;
        pre++;
    }
}


int main() {
    int i,n;
    str = (char*)malloc(sizeof(char)*1001);
    while(scanf("%s",str) != EOF){
        scanf("%d",&n);
        //左旋转
        //注意一下n需要取余就可以了,不能超过字符串自身的长度
        n = n % strlen(str);
        Reverse(str,n);
        //输出
        for(i = 0;i < strlen(str);i++){
            printf("%c",str[i]);
        }
        printf("\n");
    }//while
    return 0;
}

(3)三步翻转法


/*********************************
*   日期:2013-12-02
*   作者:SJF0115
*   题号: 题目1362:左旋转字符串(Move!Move!!Move!!!)
*   来源:http://ac.jobdu.com/problem.php?pid=1362
*   结果:AC
*   来源:剑指Offer
*   总结:
**********************************/
#include <stdio.h>
#include <malloc.h>
#include <string.h>

char *str;

//反转单词
void ReverseWord(char* words,int begin,int end){
    int temp;
    if(words == NULL || begin > end || begin < 0){
        return;
    }
    //反转
    while(begin < end){
        temp = words[begin];
        words[begin] = words[end];
        words[end] = temp;
        begin ++;
        end --;
    }
}

char* Reverse(char* str,int n){
    if(str == NULL || n < 0){
        return "";
    }
    int len = strlen(str);
    //分成两部分(1)前n项(2)剩余项
    //反转前n个
    ReverseWord(str,0,n-1);
    //反转剩余
    ReverseWord(str,n,len-1);
    //全部反转
    ReverseWord(str,0,len-1);
    return str;
}


int main() {
    int i,n;
    str = (char*)malloc(sizeof(char)*1001);
    while(scanf("%s",str) != EOF){
        scanf("%d",&n);
        //左旋转
        //注意一下n需要取余就可以了,不能超过字符串自身的长度
        n = n % strlen(str);
        str = Reverse(str,n);
        //输出
        for(i = 0;i < strlen(str);i++){
            printf("%c",str[i]);
        }
        printf("\n");
    }//while
    return 0;
}







自己按自己思路有改动。


目录
相关文章
|
人工智能 自然语言处理 文字识别
DeepMind首发游戏AI智能体SIMA:开启虚拟世界的智能探索之旅
【4月更文挑战第3天】DeepMind推出了SIMA,一种能在多个3D环境中执行语言指令的智能体,标志着AI在理解和互动虚拟世界上的进步。SIMA通过多样化的训练数据学习导航、操作、决策等技能,并结合预训练模型处理高维度输入输出。尽管在复杂任务上仍有提升空间,SIMA展现了正向迁移能力和潜力,为AI研究和未来机器人技术铺平道路。然而,仍需解决鲁棒性、可控性、评估方法及道德安全问题。
390 4
DeepMind首发游戏AI智能体SIMA:开启虚拟世界的智能探索之旅
|
自然语言处理 小程序 数据挖掘
数据分析实战-Python实现博客评论数据的情感分析
数据分析实战-Python实现博客评论数据的情感分析
566 0
|
前端开发 JavaScript API
使用 JavaScript 实现图片上传
使用 JavaScript 实现图片上传
346 1
|
关系型数据库 分布式数据库 数据库
报名啦|PolarDB数据库创新设计赛(天池杯)等你来战
2024年全国大学生计算机系统能力大赛PolarDB数据库创新设计赛(天池杯)已启动报名,面向全国高校全日制本专科学生。大赛由多家机构联合主办,旨在培养数据库领域人才,促进产学研合作,设有丰厚奖金与奖项。报名截至10月7日,决赛将于12月13日举行。更多详情及报名请访问大赛官网。
|
知识图谱
KDD 2024:Emory提出最新PolygonGNN框架:可捕捉通用多边形内外的空间关系
【9月更文挑战第16天】近年来,多边形表示学习在形状编码、建筑模式分类和地理问答等应用中至关重要。然而,现有研究多聚焦于单个多边形,忽视了多边形间复杂关系。为解决此问题,Emory大学团队提出了PolygonGNN框架,通过异质可见性图整合内外关系,并引入异质生成树采样提升计算效率。该框架设计了旋转平移不变的几何表示,适用于多种场景。实验结果显示,PolygonGNN在多个任务上表现优异,但在处理大规模场景时仍面临计算复杂度挑战,并未充分考虑拓扑结构和语义信息的影响。
167 2
|
弹性计算 运维 安全
如何使用OOS有效进行云上自动化运维
阿里云弹性计算团队十三位产品专家和技术专家共同分享云上运维深度实践,详细阐述如何利用CloudOps工具实现运维提效、弹性降本。
134675 220
将BGR色彩空间转换为YCrCb色彩空间
【5月更文挑战第13天】将BGR色彩空间转换为YCrCb色彩空间。
222 2
|
存储 SQL 分布式计算
MaxCompute的优势
【7月更文挑战第1天】MaxCompute的优势
228 0
java交换两个数字三种方法
java交换两个数字三种方法
789 0
|
存储 安全
【汇编】在代码段使用数据,在代码段使用栈
【汇编】在代码段使用数据,在代码段使用栈
630 0
【汇编】在代码段使用数据,在代码段使用栈