力扣 151 颠倒字符串中的单词 中等 Java


题目链接

https://leetcode-cn.com/problems/reverse-words-in-a-string/

1、题目要求

给你一个字符串 s ,颠倒字符串中 单词 的顺序。

单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开。

返回 单词 顺序颠倒且 单词 之间用单个空格连接的结果字符串。

注意:输入字符串 s中可能会存在前导空格、尾随空格或者单词间的多个空格。返回的结果字符串中,单词间应当仅用单个空格分隔,且不包含任何额外的空格。

示例 1:
输入:s = "the sky is blue"
输出:"blue is sky the"

示例 2:
输入:s = "  hello world  "
输出:"world hello"
解释:颠倒后的字符串中不能存在前导空格和尾随空格。

示例 3:
输入:s = "a good   example"
输出:"example good a"
解释:如果两个单词间有多余的空格,颠倒后的字符串需要将单词间的空格减少到仅有一个。

2、思路分析

在 Java 中 String 类型是不可变的,为了线程安全,可以构建字符串常量池以及可以作为 HashMap 中的 key 的使用;

在操作字符串的时候,可以使用 charAt() 函数将字符串中的每一个字符取出来使用,可以在操作的使用定义 left right 两个数组索引,或者理解成为操作数据的两个指针对于这个字符串数组进行操作;

假设原始字符串:"  hello   world "

1、将字符串中的左侧的空格过滤,右侧的空格过滤,以及字符串中间的空格过滤;
此时得到:"hello world"

2、将多余空格过滤好的字符串整体的进行翻转
此时得到:"dlrow olleh"

3、对于字符串中的每一个单词进行翻转,其翻转单词的划分就是字符串中的 ‘ ’ ;
此时得到:"world hello"

3、执行代码 Java


class Solution {
    public String reverseWords(String s) {
        // 将字符串头部 尾部 以及中间的字符进行消除
        StringBuilder sb = trimString(s);

        // 将整个字符串进行翻转
        reverse(sb, 0, sb.length() - 1);

        // 将字符串里面的单个字符逐个翻转
        reverseWord(sb);

        return sb.toString();
    }

    public StringBuilder trimString(String str) {
        StringBuilder sb = new StringBuilder();
        int left = 0;
        int right = str.length() - 1;
        while (left < right & str.charAt(left) == ' ') {
            ++left;
        }

        while (left < right & str.charAt(right) == ' ') {
            --right;
        }

        while (left <= right) {
            char temp = str.charAt(left);
            if (temp != ' ') {
                sb.append(temp);
            } else {
            	// == ' '就说明新建的 StringBuilder 中间已经存在 ' '了,不需要再次放进去一个 ' ';
                if (sb.charAt(sb.length() - 1) != ' ') {
                    sb.append(temp);
                }
            }
            ++left;
        }
        return sb;
    }


    public void reverse(StringBuilder sb, int start, int end) {
        while (start < end) {
            char temp = sb.charAt(start);
            sb.setCharAt(start, sb.charAt(end));
            sb.setCharAt(end, temp);
            start++;
            end--;
        }
    }

//    public void reverseEachWord(StringBuilder sb) {
//        int n = sb.length();
//        int start = 0, end = 0;

//        while (start < n) {

//            // 循环至单个单词的末尾
//            while (end < n && sb.charAt(end) != ' ') {
//                ++end;
//            }
//            // 翻转单词
//            reverse(sb, start, end - 1);
//            // 更新start,去找下一个单词
//            start = end + 1;
//            ++end;
//        }
//    }

     public void reverseWord(StringBuilder sb) {
         int start = 0;
         int end = 0;
         int n = sb.length();
         while (start < n) {
             // 按照 ‘ ’ 取出来中间所有的单词
             while (end < n && sb.charAt(end) != ' ') {
                 ++end;
             }

             // 循环出来调用转换
             reverse(sb,start,end - 1);

             // start 和 end 存在于同一个起跑线上面
             start = end + 1;
             ++end;
         }
     }
}

4、问题反思

4.1、& && 之间的区别

&& 是短路运算符号 可以提高算法的效率在一定程度上面

4.2、循环出来的 end 多加了 1 在后面转换的额时候,需要减去 1

在这里插入图片描述

4.3 ++ – 那些事儿

 i++; ++i;
 
 1、单独使用的时候没有区别都是自己增加 12、 但是放在表达式中含义不一样,在计算机底层的操作不一样,可以查看汇编语言确定;
 a = ++i; a = i++; 这两个不一样的,因为在表达式里面,不是单独使用的;

 3、 第三种情况就是放置在数组中的情况;
 arr[index++] 等同于 arr[index]; index++; 两句代码

5、时间复杂度以及空间复杂度分析

时间复杂度:O(n)O(n),其中 nn 为输入字符串的长度。
下面的两层 while 循环中 第二层循环只有单词的长度的次数,没有进行全部的遍历,所以时间复杂度还是O(n);

空间复杂度:Java 需要 O(n) 的空间来存储字符串

6、小结

通过基于双指针法的进行字符串单词的倒转,体会到了字符串的拼接,多个方法的联合使用以及方法互相之间的参数传递;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值