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. 空间优势:全程仅使用两个变量(index 和 res),空间复杂度为 O(1);

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

两种解法对比与适用场景

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

常见坑点提醒

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

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

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

总结

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

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

相关推荐
强哥聊算力29 分钟前
《算力江湖·英伟达传奇》第七集:ChatGPT出现前夜,英伟达发生了什么?
服务器·人工智能·算法·ai·chatgpt·gpu算力
Jmyd01233 小时前
Web端3D营销展厅技术实现路径:从素材上云到线索回流的数据链路
前端·3d·性能优化·三维数字化
砚凝霜3 小时前
【软考信息安全】第二十二章 Web服务器安全分析与增强——Apache与IIS
服务器·前端·安全
濮水大叔4 小时前
NestJS Dynamic Providers 与 Cabloy/Vona Provider Scene:同接口多实现的两种装配哲学
typescript·node.js·nestjs
Navigator_Z4 小时前
LeetCode //C - 1289. Minimum Falling Path Sum II
c语言·算法·leetcode
CCblandy4 小时前
令牌桶在 0.9 倍负载超发 19%、固定窗口边界放行 20 个:四种限流算法同构实测
后端·python·算法·性能优化·架构
mmmmath_35 小时前
LeetCode.104.二叉树的最大深度
数据结构·leetcode
u0111026755 小时前
JPG、PNG、WebP 怎么选?按透明度、体积和使用场景做判断
前端·javascript·vue.js·图像处理·ai作画
jerrywus5 小时前
让 AI 写完代码后交一份报告:我改造了 answer-me-with-html
前端·claude·cursor
YangYang9YangYan6 小时前
2027供应链计划校招:数学与应用数学专业如何把预测模型讲成业务决策?
人工智能·sql·算法