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

Posted 小智RE0

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了剑指[58]----翻转单词的顺序相关的知识,希望对你有一定的参考价值。

题目来源:剑指 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();
    
    

左指针去找有单词字符的位置,然后把右指针接过来使用;

以上是关于剑指[58]----翻转单词的顺序的主要内容,如果未能解决你的问题,请参考以下文章

剑指Offer 58 -I 翻转单词顺序

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

剑指 Offer 58 - I. 翻转单词顺序

剑指 Offer 58 - I. 翻转单词顺序

剑指 Offer 58 - I. 翻转单词顺序

LeetCode(剑指 Offer)- 58 - I. 翻转单词顺序