题目描述

[!green]

牛客原题: ✅ 补充题 124. 单词顺序反转与大小写转换

给你一个只包含英文字母和空格的字符串 s,请反转单词顺序,并将每个大写字母改为小写、每个小写字母改为大写。

保留原有空格的数量,使用字符数组完成变换,并返回结果。

示例 1:

输入: s = "Hello World"
输出: "wORLD hELLO"
解释: 反转单词顺序,再切换每个字母的大小写。

示例 2:

输入: s = "a B"
输出: "b A"
解释: 两个单词之间的一个空格保持不变。

示例 3:

输入: s = "a B"
输出: "b A"
解释: 两个单词之间的两个空格均保留。

提示:

  • 1<= n <= 10^6
  • 字符串中包括大写英文字母、小写英文字母、空格。

题意分析

单词顺序需要反转,但单词内部字母顺序不能改变。整体反转会同时改变这两层顺序,因此再逐词反转一次,就能只保留单词顺序的改变。字符数组还能原样保留每段空格数量。

解法:整体反转后恢复单词并切换大小写

核心思路

[!blue]

将字符串转成可写数组后整体反转,原末尾单词来到开头,但它的字母也倒序。扫描到空格或数组末尾时,把 [start,i-1] 这一段再次反转,便恢复该词的内部顺序,再令 start = i + 1。

连续空格对应空区间,反转函数的 l < r 条件使其自然跳过;循环包含 i == length,确保末尾没有空格的最后一词也会被处理。首尾空格随整体反转交换位置,没有被丢弃。

最后只对英文字母按大小写区间转换,空格保持不变。输入限定为英文字母和空格,所以 Java 字符数组与 Go 字节数组都能直接按位置处理。

解题步骤

  1. 将整串复制为可写数组并反转。
  2. 扫描空格分隔的每段单词,分别反转其内部字符。
  3. 只切换英文字母大小写,返回字符串。

代码实现

class Solution {
    public String transform(String s) {
        char[] a = s.toCharArray();

        reverse(a, 0, a.length - 1);
        int start = 0;

        for (int i = 0; i <= a.length; i++) {
            if (i == a.length || a[i] == ' ') {
                reverse(a, start, i - 1);
                start = i + 1;
            }
        }

        for (int i = 0; i < a.length; i++) {
            if (a[i] >= 'a' && a[i] <= 'z') {
                a[i] -= 'a' - 'A';
            } else if (a[i] >= 'A' && a[i] <= 'Z') {
                a[i] += 'a' - 'A';
            }
        }

        return new String(a);
    }

    private void reverse(char[] a, int l, int r) {
        while (l < r) {
            char t = a[l];

            a[l++] = a[r];
            a[r--] = t;
        }
    }
}
func transform(s string) string {
    a := []byte(s)
    reverse := func(l, r int) {
        for l < r {
            a[l], a[r] = a[r], a[l]
            l++
            r--
        }
    }
    reverse(0, len(a)-1)
    start := 0
    for i := 0; i <= len(a); i++ {
        if i == len(a) || a[i] == ' ' {
            reverse(start, i-1)
            start = i + 1
        }
    }
    for i, c := range a {
        if c >= 'a' && c <= 'z' {
            a[i] -= 'a' - 'A'
        } else if c >= 'A' && c <= 'Z' {
            a[i] += 'a' - 'A'
        }
    }
    return string(a)
}

复杂度分析

  • 时间复杂度:$O(n)$。
  • 空间复杂度:额外空间 $O(n)$,用于可写字符数组及结果字符串。

关键点总结

[!green]

最后逐字符切换大小写;连续空格不会被 split/join 压缩;首尾空格随整串反转交换位置。

易错点总结

[!yellow]

不能把每个单词的字母顺序也反掉;只切换字母,不修改空格;不能将字符串转数组的成本漏算。

相似题目

题目 难度 关联与区别
151. 反转字符串中的单词 中等 同样反转单词顺序,但本题保留空格数量并切换字母大小写,不能直接用压缩空格的实现。
344. 反转字符串 简单 原地反转字符区间是两次反转的基本子过程,分别用于整串和每个单词。
转载与许可
作者
链接 https://hgnulb.github.io/blog/2026/74135971
许可 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处!