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

题目:

给你一个字符串 s ,请你反转字符串中 单词 的顺序。
单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开。
返回 单词 顺序颠倒且 单词 之间用单个空格连接的结果字符串。
注意:输入字符串 s中可能会存在前导空格、尾随空格或者单词间的多个空格。返回的结果字符串中,单词间应当仅用单个空格分隔,且不包含任何额外的空格。

示例:

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

思路:

1.直接思路

class Solution {
    public String reverseWords(String s) {
        char[]  ch=s.toCharArray();//
        if(s==null||s.length() == 0){
            return s;
        }
        StringBuilder sb=new StringBuilder();//
        int i = ch.length-1;
        while(i>=0){
            while(i>=0&&ch[i]==' '){//跳过空格
                i--;
            }
            int right=i;//记录单词结束位置
            while(i>=0&&ch[i]!=' '){
                i--;//找到单词起始位置
            }
            for(int j=i+1;j<=right;j++){//j从单词起始位置到结束位置
                sb.append(ch[j]);
                if(j == right){
                    sb.append(" ");//空格
                }
            } 
        }
        //删除最后的空格
        sb.deleteCharAt(sb.length()-1);
        return sb.toString();
    }
}

tips:

s == null; 表示s还没有占用存储空间。
s.length() == 0; 表示s占用存储空间,但是其中还没有元素。

 

2.限制空间复杂度为O(1)

解题思路如下:

  • 移除多余空格
  • 将整个字符串反转
  • 将每个单词反转

举个例子,源字符串为:"the sky is blue "

  • 移除多余空格 : "the sky is blue"
  • 字符串反转:"eulb si yks eht"
  • 单词反转:"blue is sky the"
class Solution {
    public String reverseWords(String s) {
        if(s.length()==0||s==null){
            return s;
        }

        //1.移除多余空格
        StringBuilder s1=removeSpace(s);
        //2.将整个字符串反转
        int start=0;
        int end=s1.length()-1;
        StringBuilder s2=reverseString(s1,start,end);
        //3.将每个单词反转
        reverseEch(s2);
        return s2.toString();
    }
    //移除多余空格
    private StringBuilder removeSpace(String s) {
        StringBuilder sb=new StringBuilder();
        int start=0;
        int end=s.length()-1;
        //去除两端多余空格
        while(s.charAt(start)==' '){start++;}
        while(s.charAt(end)==' '){end--;}
        while(start<=end){
            //去除中间多余的空格:如果sb最后无空格,那么就保留
            if(s.charAt(start)!=' '|| sb.charAt(sb.length() - 1) != ' '){
                sb.append(s.charAt(start));
            }
            start++;
        }
        return sb;
    }
    //将整个字符串反转
    private StringBuilder reverseString(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--;
        }
        return sb;
    }
    //将每个单词反转 
    private void reverseEch(StringBuilder sb){
        int start = 0;
        int end = 1;
        int n = sb.length();
        while (start < n) {
            while (end < n && sb.charAt(end) != ' ') {//end停在距离start的第一个空格处
                end++;
            }
            reverseString(sb, start, end - 1);
            start = end + 1;//start到下一个单词第一位
            end = start + 1;//end继续重复上述步骤
        }
    }
}
StringBuilder setCharAt() 方法设置字符ch指定的索引。
String CharAt() 方法 参数只有一个index,就是取索引位置的字符。

String字符串的特点
  • Java程序中所有的双引号字符串,都是String类型的对象。

  • 字符串不可变,它们的值在创建后不能被更改。

  • 虽然String的值是不可变的,但是它们可以被共享。

 tips:

其实当需要固定规律一段一段去处理字符串的时候,要想想在在for循环的表达式上做做文章。
eg:只要让 i += (2 * k),i 每次移动 2 * k 就可以了,然后判断是否需要有反转的区间。

先整体反转再局部反转,实现了反转字符串里的单词。
后来发现反转字符串还有一个牛逼的用处,就是达到左旋的效果。

KMP的主要思想是当出现字符串不匹配时,可以知道一部分之前已经匹配的文本内容,可以利用这些信息避免从头再去做匹配了。

其实很多数组填充类的问题,都可以先预先给数组扩容带填充后的大小,然后在从后向前进行操作。

 

posted @ 2022-12-20 23:14  壹索007  阅读(44)  评论(0编辑  收藏  举报