151. 翻转字符串里的单词

题目

题目传送门(点击即可)

给你一个字符串 s ,逐个翻转字符串中的所有 单词 。

示例1

输入:s = “the sky is blue”
输出:“blue is sky the”

示例2

输入:s = “the sky is blue”
输出:“blue is sky the”

示例3

输入:s = “the sky is blue”
输出:“blue is sky the”

解题思路

法1

直接使用split函数将单词分割出来,然后将分割出来单词反过来拼接即可。如果这样,那其实不如不做这道题,他就失去了存在的意义

法2 双指针法

这里使用到两个“指针”指向一个单词,具体来说,两个指针一个指向单词开始地方,一个指向单词结束的地方,这样我们通过两个指针定位了一个单词。

那为什么要定位呢?

原因很简单,我们需要反转句子,但不反转单词,因此我们需要保证单词内各字符的有序性,通过这两个指针我们就定位了单词,因此我们只需要从后往前移动两个指针即可,这样就是实现句子反转,单词不反转。

思路
  • 初始化两指针head和tail,他们分别指向单词的头尾,初始时两个均指向句子尾端

  • step 1:判断当前tail指针所指是否为空格,如果是,向前移动即head–

    • 这里是保证tail在单词尾部,,因为句子内两单词空格数目不定,因此需要进行该操作。同时还需进行越界检查,这是因为再跳空格时可能越界,比如“ i love you”该句子开头存在空格,就会导致这种情况
  • step 2:根据tail更新head,即head=tail,然后head逆向移动,即head–,直到遇到空格,这样我们就通过head和tail定位了一个单词,这里有几个注意点:

    • head也需要进行越界检查,比如当定位第一个单词(正序的第一个单词),他前面大概率没有空格,如果不进行检查他就会一直–,这样就会越界报错
    • head后面一格到tail才是单词,因为head遇到空格才停止。因为后续涉及到提取字符串,因此这里需要搞清楚两个指针指向
  • step 3:根据两指针将单词提取出来,我这里偷懒使用了string自带的函数substring,如果不想要可以使用一个循环也可。

    • 这里有个注意点是,如果用到substring(head+1,tail+1),他参数应该如像我这样,因为head在上面提到了是指向空格,他后面一个才是单词开头,tail+1则是因为substring的提取区间是左闭右开,因此需要注意
  • step 4:将单词加入到StringBuilder对象,然后在加入一个空格

    • 这里我用了StringBuilder来添加单词,这样可以不用多次修改对象,算是一个trick吧
  • step 5:将tail指针移动到head处

  • 重复step 1-step 5,知道head tail其一指针小于0

  • step 6:返回StringBuilder对象,这里注意转换成字符串,以及最后多加了一个空格,因为我们前面操作是加一个单词就加一个空格,而最后一个单词是不需要空格的,因此我们需要去掉。我这里用到stringBuilder.substring(0,stringBuilder.length()-1),这样首先实用substing可以得到一个字符串对象省去了转换一步,其次就是子串的范围可以让我去除那个多余空格

代码 java版
public static String reverseWords(String s) {
    int head,tail;//指向单词首尾
    StringBuilder stringBuilder = new StringBuilder();
    tail = s.length()-1;
    for(head = tail;head>=0;){ // head判断这里大于0==0说明是单个单词,不然在上轮已经反转完了
        while(tail>=0&&s.charAt(tail)==' ') // 跳过空格
            --tail;
        if (tail<0)
            break;
        head = tail;
        while (head>=0&&s.charAt(head)!=' ') //不是空格 指针前移 从后往前定位一个单词
            head--;
        stringBuilder.append(s.substring(head+1,tail+1));//head+1:head当前指向空格 tail+1:substring左闭右开
        stringBuilder.append(" ");//添加空格
        tail = head;//更新单词尾部 tail向前移动
    }
    //注意此时最后一个单词一定多加了一个字符串,因此要注意去除
    return stringBuilder.substring(0,stringBuilder.length()-1);
}
执行结果

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值