LeetCode 58 Length of Last Word 详细分析

2025-06-16

题目描述

LeetCode 58. Length of Last Word(最后一个单词的长度)

给你一个字符串 s,由若干单词组成,单词前后用一些空格字符隔开。返回字符串中最后一个单词的长度

单词是指仅由字母组成、不包含任何空格字符的最大子字符串。

示例

示例 1:

输入:s = "Hello World"
输出:5
解释:最后一个单词是 "World",长度为 5。

示例 2:

输入:s = "   fly me   to   the moon  "
输出:4
解释:最后一个单词是 "moon",长度为 4。

示例 3:

输入:s = "luffy is still joyboy"
输出:6
解释:最后一个单词是 "joyboy",长度为 6。

约束条件

  • 1 <= s.length <= 10^4
  • s 仅由英文字母和空格 ' ' 组成
  • s 中至少存在一个单词

解法对比分析

解法一:字符串分割法

class Solution {
    public int lengthOfLastWord(String s) {
        String[] words = s.split(" ");
        int length = words.length;
        return words[length-1].length();
    }
}

算法思路

  1. 使用 split(" ") 方法将字符串按空格分割成字符串数组
  2. 获取数组的最后一个元素(即最后一个单词)
  3. 返回最后一个单词的长度

执行流程示例

以输入 " fly me to the moon " 为例:

步骤 操作 结果
1 s.split(" ") ["", "", "", "fly", "me", "", "", "to", "", "", "the", "moon"]
2 words.length 12
3 words[11] "moon"
4 words[11].length() 4

说明: 根据 Java String 的 split(String regex) 方法文档,当使用单参数的 split() 方法时,尾部的空字符串会被自动丢弃。因此,即使字符串末尾有空格,也不会在结果数组的末尾产生空字符串,可以直接获取数组的最后一个元素作为最后一个单词。

算法特点

  • 优点: 代码简洁,一行即可解决
  • 缺点: 仍会在中间产生空字符串(连续空格的情况),但不影响获取最后一个单词

复杂度分析

  • 时间复杂度: O(n)
    • split() 操作:O(n)
    • 总体:O(n)
  • 空间复杂度: O(n)
    • 创建字符串数组存储所有单词

解法二:反向遍历法(推荐)

class Solution {
    public int lengthOfLastWord(String s) {
        int index = s.length() - 1;
        
        // 跳过末尾的空格
        while(index >= 0 && s.charAt(index) == ' '){
            index--;
        }

        int length = 0;
        // 计算最后一个单词的长度
        while(index >= 0 && s.charAt(index) != ' '){
            length++;
            index--;
        }
        return length;
    }
}

算法思路

  1. 从字符串末尾开始向前遍历
  2. 先跳过所有末尾的空格字符
  3. 然后统计连续的非空格字符个数(即最后一个单词的长度)
  4. 遇到空格或到达字符串开头时停止

执行流程示例

以输入 " fly me to the moon " 为例:

步骤 index s.charAt(index) 操作 length
初始 23 ' ' 跳过空格 0
1 22 ' ' 跳过空格 0
2 21 'n' 开始计数 1
3 20 'o' 计数 2
4 19 'o' 计数 3
5 18 'm' 计数 4
6 17 ' ' 遇到空格,结束 4

复杂度分析

  • 时间复杂度: O(n)
    • 最坏情况下需要遍历整个字符串
    • 但实际上通常只需要遍历最后一个单词和末尾空格的长度
  • 空间复杂度: O(1)
    • 只使用了常数个额外变量

两种解法对比

对比维度 解法一(分割法) 解法二(反向遍历法)
时间复杂度 O(n) O(n)
空间复杂度 O(n) O(1)
代码简洁度 非常简洁 稍长但逻辑清晰
内存使用 需要存储所有单词 只用几个变量
边界处理 split() 自动处理末尾空格 手动处理各种情况
性能表现 较差(创建数组开销大) 较好(原地操作)
推荐指数 ⭐⭐⭐⭐ ⭐⭐⭐⭐⭐

特殊情况分析

只有一个单词

输入: "hello"
解法一结果: 5 
解法二结果: 5 

单词间多个空格

输入: "a   b"
解法一结果: 1 
解法二结果: 1 

首尾都有空格

输入: "  hello world  "
解法一结果: 5 
解法二结果: 5 

优化建议

解法一优化

public int lengthOfLastWord(String s) {
    String[] words = s.trim().split("\\s+");  // 使用正则表达式处理多个空格
    return words[words.length - 1].length();
}

解法二优化(更简洁的写法)

public int lengthOfLastWord(String s) {
    int end = s.length() - 1;
    
    // 跳过末尾空格
    while (end >= 0 && s.charAt(end) == ' ') end--;
    
    // 找到单词开始位置
    int start = end;
    while (start >= 0 && s.charAt(start) != ' ') start--;
    
    return end - start;
}

总结

对于 LeetCode 58 题,两种解法各有优势:

解法一(字符串分割法):

  • 代码极简:一行代码解决问题
  • 边界处理自动split() 方法自动丢弃尾部空字符串
  • 空间开销大:需要创建字符串数组

解法二(反向遍历法):

  • 空间效率高:O(1) 空间复杂度
  • 性能更好:避免数组创建开销
  • 面试友好:展示算法思维
  • 代码稍长:需要手动处理边界

推荐建议:

  • 简单场景或代码竞赛:优先选择解法一(简洁高效)
  • 追求极致性能或技术面试:推荐解法二(展示技术深度)

这道题很好地展示了不同解法的权衡取舍,以及Java API 使用的细节知识