LeetCode 58. 最后一个单词的长度:两种解法深度剖析

在 LeetCode 简单题中,58 题"最后一个单词的长度"看似基础,却能很好地考察对字符串处理的细节把控和算法效率的思考。题目要求我们在一个由单词和空格组成的字符串中,返回最后一个纯字母单词的长度(单词不含空格,且被若干空格分隔)。本文将带来两种主流解法,从思路、代码到优劣对比,帮你彻底吃透这道题。

题目回顾

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

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

示例 1:输入 s = "Hello World",输出 5(最后一个单词为 "World");

示例 2:输入 s = " fly me to the moon ",输出 4(最后一个单词为 "moon");

示例 3:输入 s = "luffy is still joyboy",输出 6(最后一个单词为 "joyboy")。

解法一:正则分割 + 数组取值(简洁高效款)

思路分析

这种解法的核心是利用字符串处理方法和正则表达式,将混乱的字符串转化为干净的单词数组,再直接取最后一个单词的长度。核心步骤分为两步:

  1. trim() 方法去除字符串首尾的空格,避免首尾空格对分割结果的干扰;

  2. 用正则表达式 /\s+/ 分割字符串,该正则能匹配一个或多个连续空格,完美解决"多个空格分隔单词"的问题,得到仅包含有效单词的数组;

  3. 取数组最后一个元素,返回其长度即可。

代码实现(TypeScript)

typescript 复制代码
function lengthOfLastWord_1(s: string): number {
  // 去除首尾空格后,按一个或多个空格分割为单词数组
  const sArr: string[] = s.trim().split(/\s+/);
  // 返回最后一个单词的长度
  return sArr[sArr.length - 1].length;
};

关键细节说明

  1. 为什么不用 split(' ')?直接用单个空格分割会导致连续空格产生空字符串(如示例 2 分割后会出现 ["", "fly", "me", "", "", "to", ...]),后续还要过滤空字符串,繁琐且低效;

  2. trim() 的作用?若不使用 trim(),字符串开头的空格会被 /\s+/ 匹配,分割后数组第一个元素为空字符串(如示例 2 不 trim() 会得到 ["", "fly", "me", ...]),虽不影响取最后一个元素,但会多一步无效分割;

  3. 时间复杂度:trim()split() 均为 O(n)(n 为字符串长度),整体时间复杂度 O(n);空间复杂度 O(m)(m 为单词个数),因为需要存储分割后的单词数组。

解法二:反向遍历(空间最优款)

思路分析

解法一虽简洁,但额外占用了数组空间。如果追求空间最优,可采用反向遍历的思路:从字符串末尾开始,先跳过所有末尾空格,找到最后一个单词的结尾,再继续反向遍历统计单词长度,直到遇到空格或遍历结束。核心步骤:

  1. 定义索引 index 指向字符串最后一个字符(s.length - 1);

  2. 反向遍历跳过末尾空格:当index >= 0 且当前字符是空格时,index--

  3. 统计最后一个单词长度:当 index >= 0 且当前字符不是空格时,计数器 res++index--

  4. 返回计数器 res,即为最后一个单词的长度。

代码实现(TypeScript)

typescript 复制代码
function lengthOfLastWord_2(s: string): number {
  let index = s.length - 1;
  // 跳过末尾的所有空格
  while (s[index] === ' ' && index >= 0) {
    index--;
  }
  let res = 0;
  // 统计最后一个单词的长度
  while (index >= 0 && s[index] !== ' ') {
    res++;
    index--;
  }
  return res;
};

关键细节说明

  1. 边界条件处理:index >= 0 是避免遍历越界(当字符串全为空格时,第一个循环会将 index 减至 -1,第二个循环不执行,返回 0,符合题意);

  2. 空间优势:全程仅使用两个变量(indexres),空间复杂度为 O(1);

  3. 时间复杂度:最坏情况下需遍历整个字符串(如字符串无空格),时间复杂度仍为 O(n),但无额外空间开销。

两种解法对比与适用场景

解法 时间复杂度 空间复杂度 优点 缺点 适用场景
正则分割 + 数组取值 O(n) O(m) 代码简洁、易理解,开发效率高 额外占用数组空间 日常开发、算法题快速解题,对空间要求不高的场景
反向遍历 O(n) O(1) 空间最优,无额外开销 代码稍长,需处理边界条件 空间敏感场景,如大规模字符串处理、面试中追求最优空间复杂度

常见坑点提醒

  • 忽略全空格字符串:如输入 " ",此时无有效单词,应返回 0,两种解法均能正确处理;

  • 多个连续空格分隔:解法一靠 /\s+/ 解决,解法二靠反向跳空处理,均需避免将连续空格计入单词长度;

  • 单词仅一个的情况:如输入 "Hello"" Hello",两种解法均能正确返回 5。

总结

LeetCode 58 题虽为简单题,但两种解法对应了不同的优化方向:解法一以空间换简洁,适合快速落地;解法二以时间换空间,适合追求极致性能。在面试中,若能同时给出两种解法并分析其优劣,会更受面试官青睐。

其实字符串处理类题目核心在于对细节的把控,无论是正则的灵活运用,还是遍历方向的选择,都需要结合场景权衡。希望本文能帮你掌握这道题的本质,在后续同类题目中举一反三。

相关推荐
C澒1 分钟前
Vue 项目渐进式迁移 React:组件库接入与跨框架协同技术方案
前端·vue.js·react.js·架构·系统架构
啊森要自信34 分钟前
CANN ops-cv:AI 硬件端视觉算法推理训练的算子性能调优与实战应用详解
人工智能·算法·cann
清山博客35 分钟前
OpenCV 人脸识别和比对工具
前端·webpack·node.js
要加油哦~37 分钟前
AI | 实践教程 - ScreenCoder | 多agents前端代码生成
前端·javascript·人工智能
程序员Sunday40 分钟前
说点不一样的。GPT-5.3 与 Claude Opus 4.6 同时炸场,前端变天了?
前端·gpt·状态模式
yq1982043011561 小时前
静思书屋:基于Java Web技术栈构建高性能图书信息平台实践
java·开发语言·前端
aPurpleBerry1 小时前
monorepo (Monolithic Repository) pnpm rush
前端
青茶3601 小时前
php怎么实现订单接口状态轮询请求
前端·javascript·php
仟濹1 小时前
算法打卡day2 (2026-02-07 周五) | 算法: DFS | 3_卡码网99_计数孤岛_DFS
算法·深度优先
驭渊的小故事1 小时前
简单模板笔记
数据结构·笔记·算法