剑指[58]--(1)--翻转单词的顺序

题目来源:剑指 Offer 58 - I. 翻转单词顺序
题目描述:

输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变。为简单起见,标点符号和普通字母一样处理。例如输入字符串"I am a student. ",则输出"student. a am I"。

示例 1:
输入: "the sky is blue"
输出: "blue is sky the"
 
示例 2:
输入: "  hello world!  "
输出: "world! hello"
解释: 输入字符串可以在前面或者后面包含多余的空格,但是反转后的字符不能包括。

示例 3:
输入: "a good   example"
输出: "example good a"
解释: 如果两个单词间有多余的空格,将反转后单词间的空格减少到只含一个。
 

说明:
无空格字符构成一个单词。
输入字符串可以在前面或者后面包含多余的空格,但是反转后的字符不能包括。
如果两个单词间有多余的空格,将反转后单词间的空格减少到只含一个。

使用切割字符串为数组的方法;

class Solution {
    public String reverseWords(String s) {
        //先删掉前后的空格;使用split将字符串切割为用一个或多个空格分割的数组;
        String[] strArray = s.trim().split(" +");
        //返回的字符串sb;
        StringBuilder sb = new StringBuilder();
        //倒序将数组的单词拼接;
        for (int i = strArray.length - 1; i >= 0; i--) {
            sb.append(strArray[i]);
            //填入每个单词时添加空格;
            sb.append(" ");
            //到达第一个单词,取消空格;
            if(i == 0){
                //删掉最后一个空格;
                sb.delete(sb.lastIndexOf(" "),sb.length());
            }
        }
        return sb.toString();
    }
}

效率差一点;

在这里插入图片描述

用案例试试;使用字符串"a good example";
它分隔出的数组中不会包含多余的空格,因为第一步在用空格分隔为数组时;使用了split(" +");匹配到一次或多次空格;
所以考虑到这点,在返回时要给每一个单词后都加空格;但是最后一个单词(也就是原字符串的第一个单词)比较特殊;后面不能加空格,我又用delete方法删除了这个空格;
在这里插入图片描述

优化切割字符串为数组的方法;

class Solution {
   public String reverseWords(String s) {
        //仅删掉前后的空格;使用split将字符串切割为用空格分割的数组;
        String[] strArray = s.trim().split(" ");
        //返回的字符串sb;
        StringBuilder sb = new StringBuilder();
        //倒序将数组的单词拼接;
        for (int i = strArray.length - 1; i >= 0; i--) {
            //若遇到数组元素为空元素的直接跳过;
            if (strArray[i].equals("")) {
                continue;
            }else{
               sb.append(strArray[i]);
            //填入每个单词时添加空格;
            sb.append(" "); 
            }
        }
        //最后返回的时候,再删除两边多余的空格;
        return sb.toString().trim();
    }
}

执行效率提高了
在这里插入图片描述
这次优化时,一开始并没有把字符串的所有空格都清除掉;
仅通过单个空格来间隔分隔字符串;那么得到的数组中,可能会出现放置了空格的数组元素;
那么在操作时就得考虑跳过这些元素了;
最终还是有最后一个单词的后面多余空格问题;那么最后再返回处用trim()清除一下即可;

在这里插入图片描述

使用左右指针的方式;

在这里插入图片描述

(1)左指针先向左移动;返回时,截取左指针后一位到右指针位置后一位这一段字符串
在这里插入图片描述

(2)左指针继续向左移动;遇到空格就跳过;直到找到单词字符时,就把右指针接过来;

在这里插入图片描述

(3)然后左指针先向左移动,找到空格后停止;截取这段字符串;

在这里插入图片描述

(4)这时左指针继续向左移动,找到字符a,就把右指针接过来;

在这里插入图片描述

(5)将左指针后到右指针这段字符截取;拼接过去;这时注意到左指针已经到-1了,跳出循环

在这里插入图片描述

(6) 最终返回的字符串 发现最后一位还多了一位空格;那么就考虑要删除这个空格;再进行返回;

在这里插入图片描述

class Solution {
    public  String reverseWords(String s) {
        //先清除字符串左右的空格;
        s = s.trim();
        //返回的字符串;
        StringBuilder sb = new StringBuilder();

        //刚开始左右指针都在字符串的右边位置;
        int left = s.length() - 1, right = s.length() - 1;

        //让左指针left向左移动找空格;
        while (left >= 0) {
            //左指针从右到左不断移动,先找第一个空格;
            while (left >= 0 && s.charAt(left) != ' '){
                left--;
            }
            //找到后将空格之后的这段字符串添加到返回的字符串中;且拼接一个空格;
            //注意字符串的截取方法substring(int start,int end)方法是左闭右开的;
            sb.append(s.substring(left + 1, right + 1)).append(" ");

            //左指针向左移动的过程中,若匹配到空格就跳过;
            while (left >= 0 && s.charAt(left) == ' '){
                left--;
            }
            //左指针找到不是空格的字符;就把右指针移动到左指针的位置;
            right = left;
        }
        return sb.toString().trim();
    }
}    

在这里插入图片描述

左指针去找有单词字符的位置,然后把右指针接过来使用;
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小智RE0

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值