• 《算法通关村——反转字符串中的单词问题解析》


    《算法通关村——反转字符串中的单词问题解析》

    151. 反转字符串中的单词

    给你一个字符串 s ,请你反转字符串中 单词 的顺序。

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

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

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

    示例 1:

    输入:s = "the sky is blue"
    输出:"blue is sky the"
    
    • 1
    • 2

    示例 2:

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

    示例 3:

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

    提示:

    • 1 <= s.length <= 104
    • s 包含英文大小写字母、数字和空格 ' '
    • s至少存在一个 单词

    利用API

    public String reverseWords(String s) {
            if (s == null || s.length() == 0) {
                return s;
            }
            // 除去开头和末尾的空白字符,记住这个操作
            s = s.trim();
            // 正则匹配连续的空白字符作为分隔符分割
            List<String> wordList = Arrays.asList(s.split("\\s+"));
            Collections.reverse(wordList);
            return String.join(" ", wordList);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    手写

    理解: 这里首先把所有的字符串进行一个翻转,然后把其中的单词再次反转,达到单词是正序的目的

    class Solution {
        public String reverseWords(String s) {
            StringBuilder sb = trimSpaces(s);
    
            // 翻转字符串
            reverse(sb, 0, sb.length() - 1);
    
            // 翻转每个单词
            reverseEachWord(sb);
    
            return sb.toString();
        }
    
        public StringBuilder trimSpaces(String s) {
            int left = 0, right = s.length() - 1;
            // 去掉字符串开头的空白字符
            while (left <= right && s.charAt(left) == ' ') {
                ++left;
            }
    
            // 去掉字符串末尾的空白字符
            while (left <= right && s.charAt(right) == ' ') {
                --right;
            }
    
            // 将字符串间多余的空白字符去除
            StringBuilder sb = new StringBuilder();
            while (left <= right) {
                char c = s.charAt(left);
    
                if (c != ' ') {
                    sb.append(c);
                } else if (sb.charAt(sb.length() - 1) != ' ') {
                    sb.append(c);
                }
    
                ++left;
            }
            return sb;
        }
    
        public void reverse(StringBuilder sb, int left, int right) {
            while (left < right) {
                char tmp = sb.charAt(left);
                sb.setCharAt(left++, sb.charAt(right));
                sb.setCharAt(right--, tmp);
            }
        }
    
        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;
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
  • 相关阅读:
    WPF 入门笔记 - 04 - 数据绑定 - 补充内容:资源基础
    Java IO流(详解)
    【机器学习】OpenCV入门与基础知识
    【MQ】java 从零开始实现消息队列 mq-02-如何实现生产者调用消费者?
    【uniapp】短信验证码输入框
    初识webGL
    vue3 + element 从0到1搭建前端基础框架
    音频提取:分享几个常用方法,简单好用
    【NeRF】原始论文解读
    【分布式技术专题】「Zookeeper中间件」给大家学习一下Zookeeper的”开发伴侣”—Curator-Framework(基础篇)
  • 原文地址:https://blog.csdn.net/Go_ahead_forever/article/details/134509494