day21 力扣151反转字符串中的单词

链接 151. 反转字符串中的单词 - 力扣(Leetcode)

题目

 

思路

  • 明确实现这个操作需要1.反转整个字符串 2.翻转单独的字母 3.删去多余的空格

 昨天的原代码:写法有点混乱,变量太多,重复的步骤也多,导致错误很多也不好找

char * reverseWords(char * s){
    int slen=strlen(s);
    int len=slen;
    int left=0;
    //去除最前面的空格
    while(s[left]==' ')
    {
        left++;
        len--;
    }

    //去除最右边的空格
    // int len=slen-1; 
    int right=len-1;
    if(len<0)return NULL;//注意添加必要判断
    while(s[right]==' ')
    {
        s[right]='\0';//涉及字符串的题目,记得要补充字符串结束语句
        right--;
        len--; 
    }

    //去除字符串中多余的空格
    int fast=left,slow=left;
    while(fast<len)
    {
        if(s[fast]==' '&&s[fast+1]==' ')fast++;
        else s[slow++]=s[fast++];
    }
    
    //反转整个字符串
    int m=left;
    int n=slow-1;
    for(int i=left;i<slow;i++)
    {
        char temp=s[m];
        s[m]=s[n];
        s[n]=temp;
        m++;
        n--;
    }
    
    //翻转每个单词
    for(int i=left;i<slow;i++)
    {
        int j=i;
        while(j<slow&&s[j]!=' ')
        {
            j++;
        }
        int a=i;
        int b=j-1;
        for(int i=left;i<slow;i++)
        {
            char temp=s[a];
            s[a]=s[b];
            s[b]=temp;
            a++;
            b--;
        }
        i=j;//改变i的值,使其往这个单词后遍历
    }
    return s;
}

于是简化①:进行传参,实现字母翻转(翻转整个字符串及翻转单个单词的操作通过传参进行)

char*reverse(char*s,int start,int end)
{
    int temp;
    while(start<end)
    {
        temp=s[end];
        s[end]=s[start];
        s[start]=temp;
        end--;
        start++;
    }
    return s;
}
  • 综合考虑,感觉先进行整个字符串的反转,然后进行单个单词的反转,最后进行多余空格的删除最易理解且简便 

1.进行整个字符串的反转-->直接传参

 // 1.整体反转字符串
    int slen=strlen(s);
    reverse(s,0,slen-1);

2.进行单个单词的反转:需要使用嵌套循环,固定一边端点i,另一边j往后遍历直至为空格,传参进行单词的翻转(注意,传入的末端需要j上-1)

int i=0;
    while(i<slen)
    {
        int j=i;
        while(j<slen)
        {
            if(s[j]!=' ')j++;
            else break;
        }
        if(i!=j)reverse(s,i,j-1);//2 
        i=j+1;
    }

此时选择这个顺序的好处显示出来:不许考虑两边的边界,即使左边界为空格也可以进行操作,只需要关注右边界字母和空格的分界 

一开始的写法就是错在以为还需要考虑左边界

3.进行多余空格的删除

  • 对首端空格的删除
 int left=0;
    
    // 删除字符串前端空格
    while(slen>0&&s[left]==' ')
    {
        for(int i=0;i<slen;i++)
        {
            s[i]=s[i+1];
        }
        // left++;
        slen--;
    }

注意在这个步骤中左起点一直为0不变,不需要向右遍历 !!

  •  对末端空格的删除
 int right=slen-1;
    // 删除字符串末端空格
    while(slen>0&&s[right]==' ')
    {
        s[right]='\0';
        right--;
        slen--;
    }

 注意右端在缩短,故右边界不仅要进行给出字符串结束的操作,还要向左移动

  •  对单词间多余空格的删除
 // 删除单词中多余空格
    int a=0;
    while(a<slen)
    {
        if(s[a]==' '&&s[a+1]==' ')
        {
            for(int b=a;b<slen;b++)
            {
                s[b]=s[b+1];   
            }
            slen--;
            a--;//3
        }
        a++;
    }

注意此操作中,slen减少后需进行a--,原因如下:

最终代码:

char*reverse(char*s,int start,int end)
{
    int temp;
    while(start<end)
    {
        temp=s[end];
        s[end]=s[start];
        s[start]=temp;
        end--;
        start++;
    }
    return s;
}

char * reverseWords(char * s){
    // 1.整体反转字符串
    int slen=strlen(s);
    reverse(s,0,slen-1);

    //2.翻转单个单词
    int i=0;
    while(i<slen)
    {
        int j=i;
        while(j<slen)
        {
            if(s[j]!=' ')j++;
            else break;
        }
        if(i!=j)reverse(s,i,j-1);//2 
        i=j+1;
    }

    // 3.删除多余空格
    int left=0;
    
    // 删除字符串前端空格
    while(slen>0&&s[left]==' ')
    {
        for(int i=0;i<slen;i++)
        {
            s[i]=s[i+1];
        }
        // left++;
        slen--;
    }

    int right=slen-1;
    // 删除字符串末端空格
    while(slen>0&&s[right]==' ')
    {
        s[right]='\0';
        right--;
        slen--;
    }

    // 删除单词中多余空格
    int a=0;
    while(a<slen)
    {
        if(s[a]==' '&&s[a+1]==' ')
        {
            for(int b=a;b<slen;b++)
            {
                s[b]=s[b+1];   
            }
            slen--;
            a--;//3
        }
        a++;
    }

    return s;
}

 时间复杂度O(n)空间复杂度O(1)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值