LeetCode面试150——14最长公共前缀

题目难度:简单

默认优化目标:最小化平均时间复杂度。

Python默认为Python3。

目录

1 题目描述

2 题目解析

3 算法原理及代码实现

3.1 横向扫描

3.2 纵向扫描

3.3 分治

3.4 二分查找

参考文献


1 题目描述

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

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

示例 1:

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

示例 2:

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

提示:

  • 1 <= strs.length <= 200

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

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

2 题目解析

输入一个字符串数组strs,输出strs中各单词的最长公共前缀。strs[i]表示第i个单词。暴力求解的方法是,选定strs[0],然后和strs[1]比较,找到它们的最长公共前缀。然后和strs[2]比,找到它们的最长公共前缀,依次类推。设strs的长度为n,单词的长度为m,平均时间复杂度为O(mn)。

3 算法原理及代码实现

3.1 横向扫描

即暴力求解法。依次遍历每个数组中的每个字符串,对于每个遍历到的字符串,更新最长公共前缀,当遍历完所有的字符串后,即可得到字符串数组中的最长公共前缀。

有一个特殊情况,如果最长公共字符串为空,直接返回即可,无需继续遍历。

平均时间复杂度为O(mn),平均空间复杂度为O(1)。

C++代码实现

class Solution {
public:// 主函数:找到字符串数组中的最长公共前缀string longestCommonPrefix(vector<string>& strs) {// 如果字符串数组为空,返回空字符串if (strs.empty()) {return "";}
​// 初始化最长公共前缀为第一个字符串string maxCommonPrefix = strs[0];int n = strs.size();
​// 遍历字符串数组,从第二个字符串开始for (int i = 1; i < n; i++) {// 更新最长公共前缀maxCommonPrefix = longestCommonPrefix(maxCommonPrefix, strs[i]);// 如果最长公共前缀为空,提前退出循环if (maxCommonPrefix.empty()) {break;}}return maxCommonPrefix;}
​// 辅助函数:找到两个字符串的最长公共前缀string longestCommonPrefix(const string& str1, const string& str2) {int n=min(str1.size(),str2.size());int index=0;
​while(index<n && str1[index]==str2[index]){index++;}
​return str1.substr(0,index);}
};

Python代码实现

class Solution:def longestCommonPrefix(self, strs: List[str]) -> str:n=len(strs)maxCommenPrefix=strs[0]
​if not strs:return ""
​for i in range(1,n):maxCommenPrefix=self.MCP(maxCommenPrefix,strs[i])if not maxCommenPrefix:break
​return maxCommenPrefix
​def MCP(self, str1, str2) -> str:n=min(len(str1),len(str2))index=0
​while index<n and str1[index]==str2[index]:index+=1
​return str1[:index]

3.2 纵向扫描

我们换个角度看strs,将每个单词纵向排列在一起,然后从前往后扫描每一列,直到每一列的字母不完全相同时停止。

平均时间复杂度为O(mn),平均空间复杂度为O(1)。

C++代码实现

class Solution {
public:string longestCommonPrefix(vector<string>& strs) {int n=strs.size();int m=strs[0].size();
​if(!n){return "";}
​for(int i=0;i<m;i++){char c=strs[0][i];for(int j=1;j<n;j++){if(i == strs[j].size() || c!=strs[j][i]){return strs[0].substr(0,i);}}}
​return strs[0];
​}
};

Python代码实现

class Solution:def longestCommonPrefix(self, strs: List[str]) -> str:if not strs:return ""n = len(strs)m = len(strs[0])for i in range(m):c = strs[0][i]for j in range(1, n):if i == len(strs[j]) or strs[j][i] != c:return strs[0][:i]return strs[0]

3.3 分治

根据横向扫描,有如下数学公式


LCP(S_1,\cdots,S_n)=LCP(LCP(S_1,\cdots,S_k),LCP(S_{k+1},\cdots,S_n))
 

其中,LCP(S_1,\cdots ,S_n)是字符串S_1\cdots S_n的最长公共前缀,1<k<n

因此,我们可以取k=mid=\frac{i+j}{2},对于LCP(S_i,\cdots,S_j)

平均时间复杂度为O(mn),平均空间复杂度为O(1)。

C++代码实现

class Solution {
public:// 主函数:找到字符串数组中的最长公共前缀string longestCommonPrefix(vector<string>& strs) {// 如果字符串数组为空,返回空字符串if (strs.empty()) {return "";} else {// 使用分治法找到最长公共前缀return longestCommonPrefix(strs, 0, strs.size() - 1);}}
​// 辅助函数:使用分治法找到字符串数组中的最长公共前缀string longestCommonPrefix(const vector<string>& strs, int start, int end) {// 如果只有一个字符串,返回该字符串if (start == end) {return strs[start];} else {// 计算中间位置int mid = (start + end) / 2;// 递归找到左半部分的最长公共前缀string lcpLeft = longestCommonPrefix(strs, start, mid);// 递归找到右半部分的最长公共前缀string lcpRight = longestCommonPrefix(strs, mid + 1, end);// 合并左右两部分的最长公共前缀return commonPrefix(lcpLeft, lcpRight);}}
​// 辅助函数:找到两个字符串的最长公共前缀string commonPrefix(const string& lcpLeft, const string& lcpRight) {int minLength = min(lcpLeft.size(), lcpRight.size());// 比较两个字符串的字符,找到公共前缀for (int i = 0; i < minLength; ++i) {if (lcpLeft[i] != lcpRight[i]) {return lcpLeft.substr(0, i);}}return lcpLeft.substr(0, minLength);}
};
​

Python代码实现

class Solution:def longestCommonPrefix(self, strs: List[str]) -> str:if not strs:return ""else:return self.longestCommonPrefixHelper(strs, 0, len(strs) - 1)
​def longestCommonPrefixHelper(self, strs, start, end):if start == end:return strs[start]else:mid = (start + end) // 2lcpLeft = self.longestCommonPrefixHelper(strs, start, mid)lcpRight = self.longestCommonPrefixHelper(strs, mid + 1, end)return self.commonPrefix(lcpLeft, lcpRight)
​def commonPrefix(self, lcpLeft, lcpRight):minLength = min(len(lcpLeft), len(lcpRight))for i in range(minLength):if lcpLeft[i] != lcpRight[i]:return lcpLeft[:i]return lcpLeft[:minLength]
​

3.4 二分查找

最长公共共前缀不会超过最短长度的单词,用minLength表示最短长度单词。在[0,minLength]之间使用二分查找。

平均时间复杂度为O(mn log m),平均空间复杂度O(1)。

C++代码实现

class Solution {
public:// 函数用于找到字符串数组中的最长公共前缀string longestCommonPrefix(vector<string>& strs) {// 如果输入的字符串数组为空,返回空字符串if (!strs.size()) {return "";}// 找到数组中最短字符串的长度int minLength = min_element(strs.begin(), strs.end(), [](const string& s, const string& t) {return s.size() < t.size();})->size();int low = 0, high = minLength;// 使用二分查找法寻找最长公共前缀while (low < high) {int mid = (high - low + 1) / 2 + low;if (isCommonPrefix(strs, mid)) {low = mid;} else {high = mid - 1;}}// 返回最长公共前缀return strs[0].substr(0, low);}
​// 辅助函数用于检查给定长度的前缀是否是所有字符串的公共前缀bool isCommonPrefix(const vector<string>& strs, int length) {string str0 = strs[0].substr(0, length);int n = strs.size();// 比较每个字符串的前缀与第一个字符串的前缀for (int i = 1; i < n; i++) {string str = strs[i];for (int j = 0; j < length; j++) {if (str0[j] != str[j]) {return false;}}}return true;}
};
​

Python代码实现

class Solution:def longestCommonPrefix(self, strs: List[str]) -> str:if not strs:return ""minLength = min(len(s) for s in strs)low, high = 0, minLengthwhile low < high:mid = (high - low + 1) // 2 + lowif self.isCommonPrefix(strs, mid):low = midelse:high = mid - 1return strs[0][:low]
​def isCommonPrefix(self, strs: List[str], length: int) -> bool:str0 = strs[0][:length]for i in range(1, len(strs)):if strs[i][:length] != str0:return Falsereturn True

参考文献

力扣面试经典150题

力扣官方题解

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

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

相关文章

【面试题】设计模式-责任链模式

设计模式-责任链模式 前言责任链简历案例代码小结 前言 我们知道&#xff0c;设计模式是面试时经常被问到的问题之一&#xff0c;这是因为设计模式能够体现出代码设计的美感&#xff0c;且在很多框架的底层也都会使用到各种设计模式&#xff0c;所以对设计模式的考察&#xff…

用Manim创建条形图【BarChart】

BarChart是Manim库中用于创建条形图的函数。它允许用户通过一组值创建一个条形图&#xff0c;其参数可以调整条形的外观和布局。 BarChart(values, bar_namesNone, y_rangeNone, x_lengthNone, y_lengthNone, bar_colors[#003f5c, #58508d, #bc5090, #ff6361, #ffa600],bar_w…

js第四天-函数

例1&#xff1a;选出最大值&#xff1a; <script>function getmax(x, y) {return x > y ? x : y}let max getmax(1, 3)</script> 例2&#xff1a;返回数组的最大值 <script>function getArrValue(arr []) {let max arr[0]for (let i 1; i < arr.…

基于Hadoop的共享单车分布式存储与计算

文章目录 有需要本项目的代码或文档以及全部资源&#xff0c;或者部署调试可以私信博主项目介绍研究背景研究目的和意义国内外研究现状总体研究思路数据可视化每文一语 有需要本项目的代码或文档以及全部资源&#xff0c;或者部署调试可以私信博主 项目介绍 共享单车的普及带…

Elastic 基于 RAG 的 AI 助手:使用 LLM 和私有 GitHub 问题分析应用程序问题

作者&#xff1a;来自 Bahubali Shetti 作为 SRE&#xff0c;分析应用程序比以往任何时候都更加复杂。你不仅必须确保应用程序以最佳方式运行以确保出色的客户体验&#xff0c;而且在某些情况下还必须了解内部工作原理以帮助排除故障。分析基于生产的服务中的问题是一项团队运动…

HTML “文本处理基础”--文本格式化——WEB开发系列05

HTML 的主要工作之一是赋予文本结构&#xff0c;使浏览器能够按照开发者的意图显示 HTML 文档。 在创建网页时&#xff0c;文本格式化是至关重要的&#xff0c;它不仅可以影响用户的阅读体验&#xff0c;还可以增强网页的可读性和美观性。HTML 如何通过添加标题和段落、强调单词…

中央空调系统

1.水机 它首先通过主机将水变成7度左右的冷水&#xff08;制冷&#xff09;&#xff0c;然后通过水管通过水泵输送到房间的每一端。末端的风机盘管与室内空气进行热交换&#xff0c;达到制冷的目的。供暖也是如此&#xff0c;但主机先把水变成50度左右的热水这种空调的优点是舒…

前端已经学会vue,做粒子效果

目录 1. Canvas API 2. WebGL 3. 粒子系统 4. 动画与性能优化 5. 现有库和框架 6. Vue 组件和状态管理 实践项目建议 案例1 案例2雪花 已经熟悉了 Vue、TypeScript 和 JavaScript&#xff0c;下面是一些你可以学习的内容&#xff0c;以帮助你实现粒子效果的界面&#…

享界S9+问界M9,华为智选车的高端局

作者 |老缅 编辑 |德新 8月6日&#xff0c;鸿蒙智行在北京发布D级纯电旗舰轿车&#xff0c;也是北汽 - 华为智选车合作的第一款车型&#xff0c;享界S9。 享界S9搭载了包括华为乾崑ADS 3.0在内的多项首发技术&#xff0c;全系标配100kWh华为800V巨鲸电池。 而在价格上&#…

记2024-08原生微信小程序开发

继2024.08 最近需要开发一个微信小程序的一个功能模块&#xff0c;但是之前在学的时候都是好几年前的东东了&#xff0c;然后重新快速过了一遍b站大学的教程&#xff0c;这篇文章就是基于教程进行的一些总结&#xff0c;和自己开发过程当中使用到的一些点和一些技巧什么的吧。 …

计算机网络408考研 2019

计算机网络408考研2019年真题解析_哔哩哔哩_bilibili 2019 1 1 1 1

仿RabbiteMq简易消息队列基础篇(gtest的使用)

TOC gtest介绍 gtest是google的一个开源框架&#xff0c;它主要用于写单元测试&#xff0c;检查自己的程序是否符合预期行为。可在多个平台上使用&#xff08;包含Linux&#xff0c;MAC OC&#xff0c;Windows等&#xff09;。它提供了丰富的断言&#xff0c;致命和非致命失败…

Spring Boot 3.x Filter实战:记录请求日志

上一篇&#xff1a;Spring Boot 3.x Web单元测试最佳实践 下一篇&#xff1a;Spring Boot 3.x Web MVC实战&#xff1a;实现流缓存的request 前面我们在《Spring Boot 3.x Rest API最佳实践之统一响应结构》中学习响应的统一拦截处理&#xff0c;顺带完成了响应结果的记录&am…

06:【stm32】OLED模块的简单使用

OLED模块的简单使用 OLED简单的使用 OLED简单的使用 OLED驱动函数是使用B站UP江科大的。我们直接调用即可&#xff0c;是使用软件模拟I2C协议进行通信的。具体的I2C协议可查看上官嵌入式开发中的C51单片机开发。 驱动函数文件&#xff1a;通过百度网盘分享的文件&#xff1a;…

2024 年的 Node.js 生态系统

数据来源于 Node.js Toolbox&#xff0c;网站展示了 Node.js 生态系统中积极维护且流行的库。

【Linux】lvm被删除或者lvm丢失了怎么办

模拟案例 接下来模拟lvm误删除如何恢复的案例&#xff1a; 模拟删除&#xff1a; 查看vg名&#xff1a; vgdisplayvgcfgrestore --list uniontechos #查看之前的操作 例如我删除的&#xff0c;现场没有删除就用最近的操作文件&#xff1a; 还原&#xff1a; vgcfgrestore…

Java实战一 手动创建springboot3+mybatis+mysql工程

idea手动创建sb工程&#xff0c;选择好配置&#xff0c;使用jdk17 main下补全目录resource resource下补全application.yml 引入依赖 &#xff0c;写入父工程 刷新maven 补全配置 创建所需目录 创建User实体类 创建启动类BootDemoApplication 运行启动类成功看到运行在8080端…

#include “ascii_font.c“ 引入源文件,Keil5为什么没有提示重复定义错误,详解!!!

目录 相关原理 Keil编译器规则 重点知识.c文件和.h文件的处理方式和用途 为什么在 example.c文件中需要这条指令#include "example.h" 没有包含会怎么样 配置前提 首先没有提示重复定义.c文件进行报错的前提是&#xff0c;Keil5中没有添加这源文件&#xff…

Linux服务管理(五)Apache服务优化

CustomLog "|/bin/rotatelogs -l /wwwlogs/access_%Y%m%d.log 86400" combined日志旋转可参考这篇文章&#xff1a; https://blog.csdn.net/weixin_43576565/article/details/139989701 要优化首先你得有Apache yum -y install httpd启动 service httpd start写入…

yolov8人脸识别案例

GitHub - wangWEI201901/YOLOv8-Detection-Project: &#x1f6e3;️基于YOLOv8的智慧校园人脸识别和公路汽车检测