当前位置: 首页 > news >正文

LeetCode 面试经典 150 题之最后一个单词的长度:逆向遍历高效解法

在 LeetCode 面试经典 150 题中,“最后一个单词的长度” 是一道看似简单却容易踩坑的字符串处理题。它主要考察我们对字符串边界条件(如末尾空格、单个单词、全空格字符串)的处理能力,以及是否能想到更高效的遍历方式,是面试中筛选基础编程素养的常见题目,掌握其核心思路能帮助我们快速应对类似字符串处理场景。

一、题目概览与链接

首先明确题目要求:给你一个字符串 s,由若干单词组成,单词前后用一些空格字符隔开。返回字符串中最后一个单词的长度。其中,“单词” 是指仅由字母组成、不包含任何空格字符的最大子字符串。

题目链接:LeetCode 58. 最后一个单词的长度(点击链接可直接跳转至题目页面,建议先自行尝试解题,尤其注意处理末尾空格、全空格等特殊情况)

二、解题思路深度剖析

拿到这道题,很多人第一反应是 “从左到右遍历,记录每个单词的长度,最后返回最后一个单词的长度”。但这种思路需要处理 “单词间空格”“末尾空格” 等问题,容易遗漏边界条件。而从字符串末尾逆向遍历的思路,能直接聚焦 “最后一个单词”,跳过不必要的空格处理,效率更高且逻辑更简洁。

1. 核心思路:逆向定位,跳过末尾空格

核心逻辑是 “先找最后一个单词的结尾,再找它的开头”—— 因为最后一个单词的结尾一定是字符串中 “从末尾数第一个非空格字符”,而开头则是 “从结尾往回数第一个空格字符的下一位”,两者的索引差就是单词长度。具体拆解为两个关键步骤:

步骤 1:定位最后一个单词的结尾(标记为 right)

从字符串末尾开始向前遍历,跳过所有连续的空格字符,直到找到第一个非空格字符。这个字符就是最后一个单词的最后一个字符,其索引记为 right。

  • 为什么要先跳末尾空格?因为题目中字符串可能以多个空格结尾(如 s = "Hello World "),这些空格不属于任何单词,必须先排除,才能找到真正的单词结尾。
步骤 2:定位最后一个单词的开头(标记为 left)

从 right 位置继续向前遍历,跳过所有连续的非空格字符(即最后一个单词的字符),直到找到第一个空格字符(或遍历到字符串开头)。这个空格字符的索引记为 left(若遍历到开头仍无空格,left 记为 -1,表示单词从索引 0 开始)。

步骤 3:计算单词长度

最后一个单词的长度 = right - left。因为 left 是单词开头的前一个位置(空格或字符串外),right 是单词结尾位置,两者相减刚好是单词的字符个数。

2. 具体步骤拆解(附示例)

为了让思路更直观,我们用三个典型示例演示逆向遍历的过程,覆盖常见场景:

示例 1:正常场景(末尾无空格)

s = "Hello World"(长度为 11)

  • 步骤 1:从索引 10(字符 'd')开始,因是非空格,直接定位 right = 10。
  • 步骤 2:从 10 向前遍历,依次经过 'l'(9)、'r'(8)、'o'(7)、'W'(6),到索引 5 时遇到空格,定位 left = 5。
  • 步骤 3:长度 = 10 - 5 = 5(“World” 的长度为 5,正确)。
示例 2:末尾有多个空格

s = " fly me to the moon "(末尾有 2 个空格,总长度 20)

  • 步骤 1:从索引 19(空格)向前跳,18 也是空格,到 17 时是 'n'(非空格),定位 right = 17。
  • 步骤 2:从 17 向前遍历,直到索引 11 时遇到空格(“the” 后的空格),定位 left = 11。
  • 步骤 3:长度 = 17 - 11 = 6(“moon” 的长度为 6,正确)。
示例 3:全空格或单个单词
  • 场景 A(全空格):s = " "
    • 步骤 1:从末尾向前遍历,所有字符都是空格,最终 right 未找到非空格字符(可初始化为 -1),直接返回 0(无单词,正确)。
  • 场景 B(单个单词):s = "Hello"
    • 步骤 1:从索引 4('o')定位 right = 4。
    • 步骤 2:向前遍历到索引 0('H')仍无空格,继续到 - 1(字符串开头外),定位 left = -1。
    • 步骤 3:长度 = 4 - (-1) = 5(“Hello” 的长度为 5,正确)。

3. 关键注意点

  • 边界条件处理:必须考虑 “全空格字符串”(返回 0)、“单个单词无空格”(left = -1)、“末尾多个空格”(跳过空格找 right)这三种核心场景,否则容易出现错误。
  • 遍历终止条件:逆向遍历时要注意索引不能小于 0(避免数组越界),比如在找 left 时,若遍历到索引 0 仍无空格,需停止并将 left 设为 -1。
  • 效率优势:逆向遍历无需遍历整个字符串(如示例 2 中,只需遍历末尾部分空格和最后一个单词),但最坏情况下(如全非空格字符串)仍需遍历全部字符,时间复杂度仍为 O (n),属于最优解。

三、复杂度分析

1. 时间复杂度:O (n)

  • 其中 n 是字符串 s 的长度。
  • 逆向遍历过程中,我们最多遍历整个字符串一次(如全非空格字符串:先从末尾到开头找 right(实际只需 1 步),再从 right 到开头找 left(遍历 n 步),总步数为 n+1,仍为 O (n))。所有操作均为常数时间判断,因此时间复杂度为 O (n),效率最优。

2. 空间复杂度:O (1)

  • 整个算法仅使用了 left、right 两个索引变量(或额外一个循环变量),空间占用不随字符串长度变化,始终为常数级别。因此空间复杂度为 O (1),属于 “原地算法”,内存使用高效。

四、代码实现(多语言版本)

根据上述思路,我们实现多语言代码,重点处理边界条件(如全空格、索引越界),代码简洁且易读:

1. Python 代码

class Solution:def lengthOfLastWord(self, s: str) -> int:right = len(s) - 1while right >= 0 and s[right] == ' ':right -= 1left = rightwhile left >= 0 and s[left] != ' ':left -= 1return right - left

2. Java 代码

class Solution {public int lengthOfLastWord(String s) {int n = s.length();int right = n-1;while (right >= 0 && s.charAt(right) == ' '){right--;}int left = right;while (left >= 0 && s.charAt(left) != ' '){left--;}return right-left;}
}

五、总结与拓展

“最后一个单词的长度” 这道题的核心启示是:面对 “找最后一个目标” 的问题,逆向遍历往往比正向遍历更高效。正向遍历需要记录所有单词的长度,还要处理中间空格,而逆向遍历能直接聚焦目标,减少不必要的操作,同时避免遗漏边界条件。

这道题虽然难度较低,但能很好地锻炼我们 “选择最优遍历方向” 和 “处理边界条件” 的能力 —— 而这正是面试中考察的核心素养。希望通过本文的分析,大家不仅能掌握这道题的解法,更能学会在类似问题中 “逆向思维”,提升解题效率。

如果在代码实现或思路理解上有疑问,欢迎在评论区留言讨论,一起攻克字符串处理的常见问题!


文章转载自:

http://JbMn0iAH.zkqsc.cn
http://yycn7G4c.zkqsc.cn
http://Z02MDghG.zkqsc.cn
http://AbNZIUOC.zkqsc.cn
http://o7qC0kjR.zkqsc.cn
http://WTJeAEmF.zkqsc.cn
http://3MM1PkPZ.zkqsc.cn
http://Ghe0qqjk.zkqsc.cn
http://avAI0wzv.zkqsc.cn
http://HKNWLG0M.zkqsc.cn
http://hhVRVknU.zkqsc.cn
http://hK2vCBZU.zkqsc.cn
http://Q8hXev4g.zkqsc.cn
http://6DH9Vrkg.zkqsc.cn
http://I6pF7R9v.zkqsc.cn
http://oXSMCkdj.zkqsc.cn
http://yETYPDKo.zkqsc.cn
http://CV3rG2gh.zkqsc.cn
http://3HVSnlvk.zkqsc.cn
http://3DaDcvB5.zkqsc.cn
http://80FVGzib.zkqsc.cn
http://9vCAFTaI.zkqsc.cn
http://BkrAXvzD.zkqsc.cn
http://F7JkMlcp.zkqsc.cn
http://EgbKHqkO.zkqsc.cn
http://PBwrcnvZ.zkqsc.cn
http://NeFvH9kY.zkqsc.cn
http://FtbC3Ega.zkqsc.cn
http://9q2WLGYP.zkqsc.cn
http://NbVwr64J.zkqsc.cn
http://www.dtcms.com/a/380735.html

相关文章:

  • 详解JWT
  • Spring Boot 分布式事务常见问题:Seata、XA 与本地消息表对比
  • 如何在Hugging Face中下载全部文件?
  • AI之VideoTool:AI-Video-Transcriber​​​​​​​的简介、安装和使用方法、案例应用之详细攻略
  • Qt6实现了一个打地鼠小游戏,支持AI自动打地鼠
  • Chapter5—抽象工厂模式
  • WebSocket连接状态监控与自动重连实现
  • 目标计数论文阅读(1)Class-Agnostic Counting
  • LVGL移植2048小游戏全攻略
  • 大模型系列——ChatBI重构企业知识库
  • DEM(数字高程模型)详解
  • 软考 系统架构设计师系列知识点之杂项集萃(144)
  • R语言生物群落(生态)数据统计分析与绘图实践技术应用
  • DPO 深度解析:从公式到工程,从偏好数据到可复用训练管线
  • 今天继续学习Linux系统中shell脚本
  • 开源端到端训练多模态大模型LLaVA 深度拆解
  • 周志华《机器学习导论》第10章 降维与度量学习
  • PyQt置顶窗口
  • 基于图像和激光的多模态点云融合与视觉定位
  • 企业数据防护利器:Curtain e-locker 支持NCA合规
  • 【Vue2 ✨】Vue2 入门之旅 · 进阶篇(九):Vue2 性能优化
  • Java面试问题记录(二)
  • 势能分析 线段树 学习记录
  • 创维在线算号器-Skyworth创维密码计算器
  • 电商导购平台的搜索引擎优化:基于Elasticsearch的商品精准推荐系统
  • c++怎么读取文件里的内容和往文件里写入数据
  • C++实战:搜索引擎项目(二)
  • 【Vue2 ✨】Vue2 入门之旅 · 进阶篇(七):Vue Router 原理解析
  • Java 多线程(三)
  • 【tips】el-input-number 数字输入框初始值超出限制值后,v-model的问题