最后一个单词的长度

字符串

题目描述

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

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

思路分析

计算最后一个单词的长度,有两种常见的思路:

  1. 反向遍历:从字符串的末尾开始向前遍历。先跳过所有的末尾空格,然后开始计算单词长度,遇到下一个空格或者到达字符串的开头时结束统计。这种方法直接在原字符串上操作,不需要额外的空间,空间复杂度为 O(1)
  2. 借助内置方法:将字符串去掉首尾空格后,按空格将其分割成数组,取最后一个元素的长度即可。这种方法代码简单直观,但是在分割字符串时需要创建额外的数组,空间复杂度为 O(N)

算法步骤(反向遍历)

  1. 定义变量 length = 0 用于累加单词长度,定义 i = s.length - 1 指向字符串的末尾。
  2. 首先使用 while 循环将索引 i 向前移动,跳过所有末尾的空格。
  3. 接着再使用一个 while 循环开始统计字符数量:只要当前字符不是空格,就递增 length 并将索引 i 减一。
  4. 循环结束后(遇到下一个空格或遍历到了字符串开头),返回 length 即可。

示例代码

反向遍历 (O(1) 空间)
内置方法 (O(N) 空间)
/**
 * 解法二:反向遍历
 * 空间复杂度:O(1)
 * 时间复杂度:O(N)
 */
export function lengthOfLastWord(s: string): number {
    let length = 0;
    let i = s.length - 1;

    // 1. 跳过尾部的空格
    while (i >= 0 && s[i] === ' ') {
        i--;
    }

    // 2. 计算最后一个单词的长度
    while (i >= 0 && s[i] !== ' ') {
        length++;
        i--;
    }

    return length;
}

复杂度分析

反向遍历

  • 时间复杂度O(N),其中 N 为字符串的长度。最坏情况下我们需要遍历整个字符串(比如整个字符串均为同一个长单词)。
  • 空间复杂度O(1),只需要定义常数级别的几个辅助变量。

内置方法

  • 时间复杂度O(N)trim()split() 均需要扫描字符串,时间开销与长度成比例。
  • 空间复杂度O(N)split 将会生成切分后各个单词组成的数组,需要占用由于新字符串数组分配所带来的额外内存空间。