力扣14.最长公共前缀-纵向扫描法

📋 题目描述

编写一个函数来查找字符串数组中的最长公共前缀。

如果不存在公共前缀,返回空字符串""

示例 1:

输入:strs = ["flower","flow","flight"] 输出:"fl"

示例 2:

输入:strs = ["dog","racecar","car"] 输出:"" 解释:输入不存在公共前缀。

提示:

  • 1 <= strs.length <= 200

  • 0 <= strs[i].length <= 200

  • strs[i]仅由小写英文字母组成

🧠 解题思路

核心思想:纵向扫描法

以第一个字符串为基准,逐个字符地与其他字符串比较相同位置的字符,直到发现不匹配或某个字符串结束。

算法步骤:

  1. 边界处理:如果数组为空或为null,直接返回空字符串

  2. 选取基准:以第一个字符串作为比较的基准

  3. 逐字符比较

    • 遍历基准字符串的每个字符

    • 对于每个位置,检查数组中所有字符串在该位置的字符

    • 如果发现不匹配或某个字符串已到末尾,立即返回当前已匹配的前缀

  4. 完全匹配:如果所有字符都匹配,返回整个基准字符串

💻 代码实现

java

class Solution { public String longestCommonPrefix(String[] strs) { // 边界情况处理 if(strs == null || strs.length == 0) { return ""; } // 以第一个字符串作为比较基准 String s0 = strs[0]; // 遍历基准字符串的每个字符 for(int j = 0; j < s0.length(); j++) { char c = s0.charAt(j); // 获取基准字符串当前位置的字符 // 遍历数组中的所有字符串 for(String s : strs) { // 注意:这里要先判断索引是否越界,再比较字符 if(j == s.length() || s.charAt(j) != c) { // 发现不匹配或字符串已结束,返回已匹配的前缀 return s0.substring(0, j); } } } // 所有字符都匹配,返回整个基准字符串 return s0; } }

🔍 执行过程详解

以输入["flower", "flow", "flight"]为例:

第1轮比较(j = 0):

  • 基准字符:s0.charAt(0) = 'f'

  • 检查所有字符串的第0个字符:

    • "flower"[0] = 'f'

    • "flow"[0] = 'f'

    • "flight"[0] = 'f'

  • 所有匹配,继续下一轮

第2轮比较(j = 1):

  • 基准字符:s0.charAt(1) = 'l'

  • 检查所有字符串的第1个字符:

    • "flower"[1] = 'l'

    • "flow"[1] = 'l'

    • "flight"[1] = 'l'

  • 所有匹配,继续下一轮

第3轮比较(j = 2):

  • 基准字符:s0.charAt(2) = 'o'

  • 检查所有字符串的第2个字符:

    • "flower"[2] = 'o'

    • "flow"[2] = 'o'

    • "flight"[2] = 'i'✗(不匹配!)

  • 发现不匹配,返回s0.substring(0, 2) = "fl"

最终结果:"fl"

⚡ 复杂度分析

时间复杂度:O(S)

  • 其中 S 是所有字符串中字符的总数

  • 在最坏情况下,算法会检查每个字符串的每个字符

  • 但通常情况下一旦发现不匹配就会提前结束,实际运行时间通常小于 O(S)

空间复杂度:O(1)

  • 只使用了常数级别的额外空间

  • 没有使用额外的数据结构

🎯 关键点解析

1.边界条件处理的顺序

java

// ❌ 错误写法(可能导致数组越界) if(c != s.charAt(j) || j == s.length()) // ✅ 正确写法(利用短路原则) if(j == s.length() || s.charAt(j) != c)

重要原则:先检查索引是否有效,再访问该索引处的元素。

2.charAt()方法

  • 用于获取字符串中指定位置的字符

  • 索引从0开始,最大索引为length()-1

  • 如果索引越界会抛出StringIndexOutOfBoundsException

3.substring()方法

  • 用于提取字符串的一部分

  • substring(0, j)提取索引0到j-1的字符(不包含j)

  • 当j=0时,返回空字符串""

🔄 其他解法对比

1.横向扫描法

public String longestCommonPrefix(String[] strs) { if(strs == null || strs.length == 0) return ""; String prefix = strs[0]; for(int i = 1; i < strs.length; i++) { while(strs[i].indexOf(prefix) != 0) { prefix = prefix.substring(0, prefix.length() - 1); if(prefix.isEmpty()) return ""; } } return prefix; }
  • 思路:将前一个字符串的公共前缀与后一个字符串比较,不断缩减前缀

  • 时间复杂度:O(S),其中S是所有字符串字符总数

2.分治法

public String longestCommonPrefix(String[] strs) { if(strs == null || strs.length == 0) return ""; return divideAndConquer(strs, 0, strs.length - 1); } private String divideAndConquer(String[] strs, int left, int right) { if(left == right) return strs[left]; int mid = (left + right) / 2; String leftPrefix = divideAndConquer(strs, left, mid); String rightPrefix = divideAndConquer(strs, mid + 1, right); return commonPrefix(leftPrefix, rightPrefix); } private String commonPrefix(String str1, String str2) { int minLength = Math.min(str1.length(), str2.length()); for(int i = 0; i < minLength; i++) { if(str1.charAt(i) != str2.charAt(i)) { return str1.substring(0, i); } } return str1.substring(0, minLength); }
  • 思路:将问题分解为子问题,合并结果

  • 时间复杂度:O(S)

  • 优点:适合并行处理

3.二分查找法

public String longestCommonPrefix(String[] strs) { if(strs == null || strs.length == 0) return ""; int minLength = Integer.MAX_VALUE; for(String str : strs) { minLength = Math.min(minLength, str.length()); } int left = 0, right = minLength; while(left < right) { int mid = (left + right + 1) / 2; if(isCommonPrefix(strs, mid)) { left = mid; } else { right = mid - 1; } } return strs[0].substring(0, left); } private boolean isCommonPrefix(String[] strs, int length) { String prefix = strs[0].substring(0, length); for(int i = 1; i < strs.length; i++) { if(!strs[i].startsWith(prefix)) { return false; } } return true; }
  • 思路:对前缀长度进行二分查找

  • 时间复杂度:O(S·log m),其中m是最短字符串长度

  • 优点:当字符串很长时效率更高

📝 常见错误及避免方法

错误1:忘记处理空数组

java

// ❌ 错误:如果strs为空,会抛出NullPointerException String s0 = strs[0]; // ✅ 正确:先检查数组是否为空或null if(strs == null || strs.length == 0) { return ""; }

错误2:索引越界

java

// ❌ 错误:可能先访问s.charAt(j)导致越界 if(s.charAt(j) != c || j == s.length()) // ✅ 正确:先检查索引是否有效 if(j == s.length() || s.charAt(j) != c)

错误3:没有考虑字符串长度不同的情况

java

// ❌ 错误:假设所有字符串长度相同 for(int j = 0; j < s0.length(); j++) { // 如果没有检查j == s.length(),当s较短时会越界 } // ✅ 正确:在比较字符前检查字符串长度 if(j == s.length() || s.charAt(j) != c)

🏆 总结

本文介绍的纵向扫描法是最直观且高效的解法,具有以下优点:

  1. 代码简洁:仅需10余行代码即可实现

  2. 逻辑清晰:逐字符比较的思路容易理解

  3. 效率高:一旦发现不匹配立即返回,避免不必要的比较

  4. 空间优:只使用常数级别的额外空间

关键技巧

  • 以第一个字符串为基准

  • 利用短路原则避免索引越界

  • 使用substring()返回已匹配的前缀

掌握这种方法不仅能解决最长公共前缀问题,其中的思想(逐位比较、提前终止)也能应用于其他字符串处理问题中。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1190555.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

用ppt绘制新的形状

通过PPT的组合和合并形状来绘制图片

新写的launch文件不能用tab补全

博客地址:https://www.cnblogs.com/zylyehuo/系统环境:ros1 noetc问题描述 launch文件不能用tab补全全部手敲是能运行的(执行完 source ./devel/setup.bash)解决方法Tab 补全失败的原因通常是 ROS 的包索引缓存(ros…

灵遁者诗歌:演员之镜 · 真实的演技

33. 【外卖员之镜 算法的脚注】他的运动轨迹&#xff0c;是城市血管里一颗被算法驱动的红细胞。准时率是他的血氧饱和度。在每一个红绿灯的间隙&#xff0c;他抬头望了一眼高楼里格子状的灯光。那其中一扇窗&#xff0c;是他今天送过的晚餐&#xff0c;也是他永远无法抵达的“…

20260120 - Linux驱动学习笔记:SPI子系统核心层到具体硬件驱动

详细追踪从spi.c中的函数接口 spi_write() 到 spi-imx.c 中具体硬件操作的完整调用链。 完整的函数调用链 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 第1步&#xff1a;应用层/设备驱动调用 ━━━━━━━…

从0到1成为大模型应用开发工程师:154万年薪岗位全解析

大模型应用开发工程师成为高薪职业&#xff08;154万年薪&#xff09;&#xff0c;因市场需求大而人才稀缺。这类工程师需掌握提示词工程、RAG、模型微调等技术&#xff0c;同时具备工程开发、AI理解和业务洞察的复合能力。文章提供分层学习路径和实战项目建议&#xff0c;帮助…

【物理应用】滑块-曲柄机构Matlab仿真

✅作者简介&#xff1a;热爱数据处理、建模、算法设计的Matlab仿真开发者。&#x1f34e;更多Matlab代码及仿真咨询内容点击 &#x1f517;&#xff1a;Matlab科研工作室&#x1f34a;个人信条&#xff1a;格物致知。&#x1f525; 内容介绍滑块 - 曲柄机构是机械传动领域最基础…

Serv-U+cpolar 让文件远程访问像连 Wi-Fi 一样简单

Serv-U 作为一款成熟的文件服务软件&#xff0c;核心功能围绕文件的共享与传输展开&#xff0c;支持 FTP/FTPS/SFTP 等多种协议&#xff0c;既能实现大文件断点续传&#xff0c;也能精细化分配用户权限&#xff0c;比如给普通员工只读权限、给管理人员修改权限&#xff0c;适配…

救命神器9个AI论文软件,自考学生轻松搞定毕业论文!

救命神器9个AI论文软件&#xff0c;自考学生轻松搞定毕业论文&#xff01; 自考论文写作的救星&#xff1a;AI工具如何帮你轻松应对 对于自考学生而言&#xff0c;撰写毕业论文是一项既复杂又耗时的任务。从选题、收集资料到撰写初稿、反复修改&#xff0c;每一步都可能让人感到…

【YOLO模型导出格式】大全

一行命令即可完成模型格式转换,了解每种格式的设计逻辑才能在实际部署中做出最佳选择。 YOLO模型在训练完成后,我们通常会将其从PyTorch格式导出为多种不同格式。这些格式不仅代表着不同的文件扩展名,更代表着为不同硬件平台和部署场景量身定做的优化策略。 从旨在最大化C…

【Science Advances】“安全可触”的低电压仿生人工肌肉,让机器人更柔、更轻、更安全

在机器人领域&#xff0c;刚性机器人虽然精度高&#xff0c;但在需要柔顺性、抗干扰性或高能效的复杂环境中往往力不从心。为此&#xff0c;科学家们致力于研发仿生机器人&#xff0c;尤其是模仿人体肌肉的“人工肌肉”。其中&#xff0c;电液致动器因具备与哺乳动物肌肉相媲美…

世界棋局:国家、巨头与文明的AI竞赛以及星链的最新发展

第三章&#xff1a;终极棋局&#xff1a;国家、巨头与文明的AI竞赛“当算力成为新军备&#xff0c;数据成为新疆域&#xff0c;星球级的智慧博弈已悄然布子。”在前两章&#xff0c;我们剖析了AI作为新物种的觉醒与其产业狩猎的逻辑。现在&#xff0c;让我们将视野拉升到星球尺…

【粉丝福利社】驾驭Gemini 3与Nano Banana:人人都是AI产品创客

你好&#xff0c;未来的创造者&#xff01; 2025 年&#xff0c;AI 编程已成爆发之势—— Cursor 年收入破 10 亿美元&#xff0c;斯坦福学生“不写一行代码”就能交作业…… 这背后&#xff0c;是一个明确的信号&#xff1a;编程的核心&#xff0c;正从“写代码”转向“定义需…

NLP技术视角下的论文优化:2026主流降重平台算法与效果深度横评 - 品牌观察员小捷

在AIGC检测算法全面升级的2026年,解决“哪个降重平台效果最好”的问题,已不再是简单的同义词替换(Synonym Replacement),而是涉及困惑度(Perplexity)对抗、语义重构(Semantic Refactoring)以及命名实体识别(…

如何下载Spring源码 - 详解

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

2. C语言核心语法 - 实践

2. C语言核心语法 - 实践2026-01-20 19:35 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; fo…

Linux驱动学习:验证MasterDriverDevice三方匹配成功

实验日志&#xff1a; [root100ask:/proc/device-tree]# find -name "oled" ./soc/aips-bus02000000/spba-bus02000000/ecspi02008000/oled [root100ask:/proc/device-tree]# cd /root/ [root100ask:~]# insmod oled_drv.ko [ 119.745706] 100ask_spi_oled_drv spi0…

华为笔记本安装Ubuntu系统,声卡没有声音的处理

从网站:https://github.com/Smoren/huawei-ubuntu-sound-fix/,下载安装包,并安装即可

必看!AI架构师珍藏手册:1.5万字深度解析如何把AI关进确定性系统笼子

文章提出AI系统架构"四大生理系统"框架&#xff0c;将大模型从全能指挥官降级为心脏&#xff0c;系统逻辑接管决策。强调架构设计应遵循祛魅、解耦、归因三大法则&#xff0c;把概率性AI关进确定性系统。提供基于不确定性的技术选型指南&#xff0c;包含组件边界判定…

必收藏!基于模板-定理图谱的LLM数学推理增强技术,性能提升超乎想象!

本文提出了一种基于模板-定理图谱的数学推理增强框架&#xff0c;通过结构化关联问题模板与数学定理&#xff0c;模仿人类联想记忆机制&#xff0c;显著提升LLM在复杂数学问题上的推理能力。该方法利用LLM自动构建高质量知识图谱&#xff0c;设计高效检索与融合机制&#xff0c…

AES加密密钥安全存储、iOS设备管理实现方式Kafka能够实时收集、处理和分析用户行为数据,从而生成动态更新的用户画像AES加密密钥安全存储

AES加密密钥安全存储、iOS设备管理实现方式Kafka能够实时收集、处理和分析用户行为数据&#xff0c;从而生成动态更新的用户画像AES加密密钥安全存储 AES加密密钥安全存储、iOS设备管理实现方式Kafka能够在数据安全日益重要的今天&#xff0c;AES&#xff08;高级加密标准&…