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

news2024/9/23 13:21:13

题目难度:简单

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

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) // 2
            lcpLeft = 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, minLength
        
        while low < high:
            mid = (high - low + 1) // 2 + low
            if self.isCommonPrefix(strs, mid):
                low = mid
            else:
                high = mid - 1
        
        return 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 False
        return True

参考文献

力扣面试经典150题

力扣官方题解

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

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

相关文章

MyBatis 基本操作 - 注解版

目录 一&#xff0c;查询 - select 1.1 全列查询 1.2 指定列查询 1.3 赋值问题 方法一&#xff1a;起别名 方法二&#xff1a;结果映射 方法三&#xff1a;添加配置 二&#xff0c;新增 - Insert 2.1 使用对象插入 2.2 获取主键 三&#xff0c;删除 - Delete 四&am…

使用Gitlab实现monorepo多项目CICD

CI/CD是什么 CI/CD&#xff08;Continuous Intergration/Continuous Delpoy&#xff09;&#xff0c;即持续集成/持续部署&#xff0c;或称为持续集成/持续交付&#xff0c;作为一套面向开发和运维团队的解决方案&#xff0c;CI/CD 主要解决集成新代码和向用户频繁交付应用的问…

SQL注入实例(sqli-labs/less-22)

0、初始页面 1、确定闭合字符 闭合字符为单引号双引号 2、爆库名 3、爆表名 4、爆列名 5、查询最终目标

初识redis:String类型

在Redis中的所有key都是字符串&#xff0c;而value的类型是存在差异的。本文介绍的就是value中的string类型。 首先要知道&#xff0c;Redis中的字符串&#xff0c;直接就是按照二进制数据的方式存储的&#xff0c;不会做任何的编码转换。也就是说&#xff0c;redis不仅仅可以…

JMeter——异步请求性能测试

前段时间任务要求要对一种异步请求做性能测试&#xff0c;异步请求步骤如下&#xff1a; step1: 发一个数据计算的请求&#xff0c;response里面返回一个jobId step2: 带上这个jobId&#xff0c;就可以实时查看这个请求返回的jobStatus, 如果jobStatus0, 则成功返回计算结果&…

29_反序列化漏洞、反序列化概念、反序列化原理、反序列化漏洞防御、序列化

概念 序列化和反序列化 序列化 将对象型转换成字符串的过程。 反序列化 将字符串还原成对象型的过程。 反序列化漏洞&#xff08;了解&#xff09; 便于传输和存储 接下来上代码进行测试&#xff0c;先搞个类&#xff0c; <?phpheader("content-type:text/html;…

基于SpringBoot+Vue的校园失物招领系统(带1w+文档)

基于SpringBootVue的校园失物招领系统(带1w文档) 基于SpringBootVue的校园失物招领系统(带1w文档) 本课题研发的校园失物招领系统管理系统&#xff0c;就是提供校园失物招领系统信息处理的解决方案&#xff0c;它可以短时间处理完信息&#xff0c;并且这些信息都有专门的存储设…

51单片机个人学习笔记16(红外遥控)

前言 本篇文章属于STC89C52单片机&#xff08;以下简称单片机&#xff09;的学习笔记&#xff0c;来源于B站教学视频。下面是这位up主的视频链接。本文为个人学习笔记&#xff0c;只能做参考&#xff0c;细节方面建议观看视频&#xff0c;肯定受益匪浅。 [1-1] 课程简介_哔哩…

Qt编程技巧小知识点(2)GPIB缓存区数据读取

文章目录 Qt编程技巧小知识点&#xff08;2&#xff09;GPIB缓存区数据读取小结 Qt编程技巧小知识点&#xff08;2&#xff09;GPIB缓存区数据读取 大端小端的问题&#xff0c;其主要表现如下例子&#xff1a; 例如&#xff1a;输入为QByteArray str "#14M\xB6q\xC1\n&qu…

ImageNet_2014数据集下载与解压

前言 最近在配OpenLongTailRecognition-OLTR代码用的ImageNet_2014&#xff0c;因为数据集较大的原因&#xff0c;导致下载和数据集配置一直被耽误&#xff0c;进度很满&#xff0c;故此记录&#xff0c;以背不时只用。 进入imageNet主页 注: 需要注册账号&#xff0c;教育邮箱…

【论文阅读】MobileNetV4 - Universal Models for the Mobile Ecosystem

文章目录 摘要一、介绍二、相关工作三、与硬件无关的帕累托效率四、通用倒置瓶颈五、移动MQA六、MNv4模型的设计6.1 为增强的体系结构改进NAS6.2 MNv4模型的优化 7. 结果7.1 ImageNet分类7.2 COCO目标检测 8. 强化蒸馏配方9. 结论 MobileNetV4 - 移动生态系统的通用模型 摘要 …

linux系统编程:(4)

1.系统时间的获取函数 1. time函数 功能: 获得1970年到现在的秒数 参数: t:存放秒数的空间首地址 返回值: 成功返回1970年到现在的秒数 失败返回-1 2.localtime 函数 功能: 将一个秒数转化成日历时间 参数: timep:保存秒数空间的地址 返回值: 成功…

Node.js异步编程

【图书介绍】《Node.jsMongoDBVue.js全栈开发实战》-CSDN博客 《Node.jsMongoDBVue.js全栈开发实战&#xff08;Web前端技术丛书&#xff09;》(邹琼俊)【摘要 书评 试读】- 京东图书 (jd.com) 本节主要介绍Node.js异步编程的相关内容。内容包括 同步API、异步API、同步API与…

拿捏!远程观影之详细操作教程

碎碎念 相信不少小伙伴是有收藏影片的&#xff0c;时不时会取出来进行观看。大多时候&#xff0c;我们都是在局域网中观影&#xff0c;局域网中是直连&#xff0c;所以可以一直流畅进行观影&#xff0c;但是有不少朋友是有远程观影需求的&#xff0c;那么怎么实现能随时在手机…

squidpy学习总结

下载安装 首先不要使用pip install squidpy[interactive] 安装&#xff0c;因为我在base环境里python版本是python3.11.5, 导致安装narapi包的时候出现问题&#xff0c;所以我选择的办法是 conda create -n sp_env python3.9.12 注意这个有个问题&#xff0c;我的mac为啥建立不…

【git】git与​TortoiseGit​下载教程

下载地址&#xff1a;https://git-scm.com/ 下载TortoiseGit 官网链接&#xff1a;https://tortoisegit.org/ 拉去代码错误&#xff1a; 找到在本地安装的 git 服务的根目录 -> Git -> usr -> bin 目录下选中 ssh.exe &#xff0c;再点击打开即可&#xff0c;如下图&a…

在Ubuntu上基于NDK(r21)交叉编译FFmpeg for Android

各软件版本号&#xff1a;VMware为17 Pro、FFmpeg版本号为4.3.8、NDK版本号为r21e、Ubuntu版本号为20.04 1.下载FFmpeg4.3.8并解压 2.下载NDK&#xff08;r21e&#xff09;并解压 https://dl.google.com/android/repository/android-ndk-r21e-linux-x86_64.zip 3.在ffmpeg-4.…

FastReport数据区横向排列展示

FastReport数据区横向排列展示 步骤1&#xff1a;设置数据区的Columns Editor属性 1、Count&#xff1a;2表示数据区里的控件将最多显示两列 2、AcrossThenDown&#xff1a;数据区里的控件将会被从做到右依次循环遍历 3、Width&#xff1a;9.25&#xff0c;因为我只设置了两列…

mmdebstrap:创建 Debian 系统 chroot 环境的利器 ️

文章目录 mmdebstrap 的一般性参数说明 &#x1f4dc;mmdebstrap 的常见用法示例 &#x1f308;使用 mmdebstrap 的注意事项 ⚠️ &#x1f308;你好呀&#xff01;我是 山顶风景独好 &#x1f388;欢迎踏入我的博客世界&#xff0c;能与您在此邂逅&#xff0c;真是缘分使然&am…

我的创新大赛经验分享:如何打磨优化项目

我的创新大赛经验分享&#xff1a;如何打磨优化项目 前言1. 强化创新性与独特性2. 深度市场调研与用户需求洞察3. 优化商业模式与财务规划4. 提升团队表现与协作效率5. 完善展示材料与演示技巧6. 模拟答辩与专家评审7. 关注细节与排除潜在问题结语 前言 在创新的浪潮中&#xf…