题目


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

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

  • 示例 1:

    输入: [“flower”,“flow”,“flight”]
    输出: “fl”

  • 示例 2:

    输入: [“dog”,“racecar”,“car”]
    输出: “”

  • 解释: 输入不存在公共前缀。

  • 说明:
    所有输入只包含小写字母 a-z 。

    来源:力扣(LeetCode)
    链接:https://leetcode-cn.com/problems/longest-common-prefix
    著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

我的解答

想好大致思路开写,虽然出了点小问题,但是最后还是AC了,说一下出现的小问题:

  • 对于只有一个单词的情况,公共前缀为这个单词本身,开始按照return ""来处理了

  • 对于数组越界的问题,就是没考虑到 后面的单词长度 小于 前面单词的长度,导致得到的前缀 长于 实际正确前缀

    其实这种情况会造成越界异常,但是开始我 是 解决了越界问题,但是 导致得到的前缀 长于 实际正确前缀


    最会干脆直接抓就完了!!速度感人~哈哈

代码
class Solution {public String longestCommonPrefix(String[] strs) {if(strs.length == 0){return "";}//需要注意,当只有一个单词 的时候,公共前缀为 此单词本身else if(strs.length == 1){return strs[0];}StringBuffer res = new StringBuffer();int count = 0;boolean sameFlag = true;//第一个单词为基准for(int i = 0;i<strs[0].length();i++){char ch = strs[0].charAt(i);//注意 条件的前后顺序,否则可能会越界 开始想着  j<strs.length $$ j<strs.length 解决越界问题//但是 虽然不越界了,但是答案错误,原因是 当出现 后面单词 长度 小于 第一个基准单词的情况//就会 后续字母 不在进入循环,这也是为啥越界的 原因//干脆直接抓就完了!try{for(int j = 1;j<strs.length ;j++){if(strs[j].charAt(i) == ch){continue;}else{sameFlag = false;break;}}if(sameFlag){res.append(ch);continue;}else{break;}}catch(Exception e){}}String res_str = new String(res);return res_str;}}

题解

解法多种:

  • 横向扫描
  • 纵向扫描
  • 分治
  • 二分查找
  • 秀儿操作之排序比较头尾
一、横向扫描


求所有单词的 的最长公共前缀。可以得到以下结论:LCP(单词1,单词2,...,单词n) = LCP(LCP(LCP(单词1,单词2),单词3),...,单词n)

基于该结论,可以得到一种查找字符串数组中的最长公共前缀的简单方法。

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

简单理解:

就是拿 前面相邻的两个单词的公共前缀 去 和 后面单词去匹配

  • 匹配成功(最长前缀 在 目标单词中),前缀保持不更新,接着 和 后面未匹配 的 单词,依次匹配
  • 匹配失败,求出此时的最长公共前缀,更新前缀

需要注意

  • 如果在尚未遍历完所有的字符串时,最长公共前缀已经是空串,则最长公共前缀一定是空串,因此不需要继续遍历剩下的字符串,直接返回空串即可。

    作者:LeetCode-Solution
    链接:https://leetcode-cn.com/problems/longest-common-prefix/solution/zui-chang-gong-gong-qian-zhui-by-leetcode-solution/
    来源:力扣(LeetCode)
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  • 代码

class Solution {public String longestCommonPrefix(String[] strs) {//空单词的处理if (strs == null || strs.length == 0) {return "";}//开始最大前缀为 第一个单词,之后 求 第一个、第二个单词的最长前缀....String prefix = strs[0];int count = strs.length;for (int i = 1; i < count; i++) {prefix = longestCommonPrefix(prefix, strs[i]);//进行的过程中,出现 最长字串为 空 ,就结束if (prefix.length() == 0) {break;}}return prefix;}public String longestCommonPrefix(String str1, String str2) {//以长度短的为基准,最大前缀的长度,最多和 最短的单词 长度一样长int length = Math.min(str1.length(), str2.length());int index = 0;while (index < length && str1.charAt(index) == str2.charAt(index)) {index++;}//返回最大前缀字符串return str1.substring(0, index);}
}

复杂度分析:

  • 时间复杂度:O(mn)O(mn),其中 mm 是字符串数组中的字符串的平均长度,nn 是字符串的数量。最坏情况下,字符串数组中的每个字符串的每个字符都会被比较一次。

  • 空间复杂度:O(1)O(1)。使用的额外空间复杂度为常数

二、纵向扫描

前面的 横向扫描 是 依次遍历每个字符串,然后更新 最长前缀

这里的 纵向扫描 是 从前往后遍历每个字符串的每一列,比较相同列 上的字符是否相等,

如果不相同当前列不属于 公共前缀,取之前列的部分,就是前面我的解答那种实现

  • 代码
class Solution {public String longestCommonPrefix(String[] strs) {if (strs == null || strs.length == 0) {return "";}//和我的解答思想类似,以第一个单词为基准int length = strs[0].length();//总单词数int count = strs.length;for (int i = 0; i < length; i++) {//依次取第一个单词的每个字母char c = strs[0].charAt(i);//用 取出的 单词 和剩下单词的对应位置 匹配for (int j = 1; j < count; j++) {//它这里的 不越界判断,当 剩下单词 出现 等于 当前最大公共前缀的长度时候,就该结束了if (i == strs[j].length() || strs[j].charAt(i) != c) {//返回前缀return strs[0].substring(0, i);}}}//这是只有一个单词的情况return strs[0];}
}

效率分析:

  • 时间复杂度:O(mn)O(mn),其中 mm 是字符串数组中的字符串的平均长度,nn 是字符串的数量。最坏情况下,字符串数组中的每个字符串的每个字符都会被比较一次。

  • 空间复杂度:O(1)O(1)。使用的额外空间复杂度为常数。

三、分治

前面横向扫描的LCP 在进行最长前缀 和 目标单词匹配的时候,可以按照从一端顺序依次取单词,

当然也可以从两端同时进行

  • 可以分解成两个子问题:LCP(s1,s2,...,smid)LCP( S mind + 1,....,Sn)

  • 然后对两个子问题的解计算最长公共前缀,即为原问题的解。

  • 代码
class Solution {public String longestCommonPrefix(String[] strs) {if (strs == null || strs.length == 0) {return "";} else {//不是空单词return longestCommonPrefix(strs, 0, strs.length - 1);}}//求最长前缀函数,递归public String longestCommonPrefix(String[] strs, int start, int end) {if (start == end) {return strs[start];} else {int mid = (end - start) / 2 + start;//递归分治左半部分String lcpLeft = longestCommonPrefix(strs, start, mid);//递归分治右半部分String lcpRight = longestCommonPrefix(strs, mid + 1, end);//左半部分、右半部分去公共前缀return commonPrefix(lcpLeft, lcpRight);}}//左半部分、右半部分去公共前缀,和上面的 横向扫描类似public String commonPrefix(String lcpLeft, String lcpRight) {//以长度短的为基准int minLength = Math.min(lcpLeft.length(), lcpRight.length());       for (int i = 0; i < minLength; i++) {//当前位置 字母 不一样if (lcpLeft.charAt(i) != lcpRight.charAt(i)) {return lcpLeft.substring(0, i);}}//恰好一样,返回哪个都行return lcpLeft.substring(0, minLength);}
}

效率分析

  • 时间复杂度:O(mn)O(mn),其中 mm 是字符串数组中的字符串的平均长度,nn 是字符串的数量。时间复杂度的递推式是 T(n)=2 * T(n/2)+O(m),通过计算可得 T(n)=O(mn)

  • 空间复杂度:O(mlogn),其中 mm 是字符串数组中的字符串的平均长度,n 是字符串的数量。空间复杂度主要取决于递归调用的层数,层数最大为 logn,每层需要 m 的空间存储返回结果。

四、二分查找

显然,最长公共前缀的长度不会超过字符串数组中的最短字符串的长度。

用 minLength 表示字符串数组中的最短字符串的长度,

则可以在 [0,minLength] 的范围内通过二分查找得到最长公共前缀的长度。

每次取查找范围的中间值 mid,判断每个字符串的长度为mid 的前缀是否相同,

  • 如果相同则最长公共前缀的长度一定大于或等于 mid,
  • 如果不相同则最长公共前缀的长度一定小于 mid,

通过上述方式将查找范围缩小一半,直到得到最长公共前缀的长度。

  • 代码
class Solution {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 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].substring(0, low);}public boolean isCommonPrefix(String[] strs, int length) {String str0 = strs[0].substring(0, length);int count = strs.length;for (int i = 1; i < count; i++) {String str = strs[i];for (int j = 0; j < length; j++) {if (str0.charAt(j) != str.charAt(j)) {return false;}}}return true;}
}
五、先排序后比较头尾

先将所有的单词排序,选首、尾单词进行 截取 最大公共前缀

单词字符串的排序是按照 相同字母的肯定在一堆儿,及中间的单词 首字母一定 和首尾的相同

  • 若 首单词和为尾单词 第一个字母不一样的情况,最长前缀一定是 空

但是 字符串排序太耗时,不推荐

class Solution {public:string longestCommonPrefix(vector<string>& strs) {if(strs.empty()) return string();//排序sort(strs.begin(), strs.end());//去排序后的第一个、最后一个单词string st = strs.front(), en = strs.back();//求第一个单词和最后一个单词的最小长度int i, num = min(st.size(), en.size());for(i = 0; i < num && st[i] == en[i]; i ++);return string(st, 0, i);}
};

LeetCode4_编写一个函数来查找字符串数组中的最长公共前缀。 如果不存在公共前缀,返回空字符串 ““。(解决方案:横向扫描、 纵向扫描 、分治 二分查找 、秀儿操作之排序比较头尾)相关推荐

  1. 20190501-编写一个函数来查找字符串数组中的最长公共前缀。如果不存在公共前缀,返回空字符串...

    题目描述 编写一个函数来查找字符串数组中的最长公共前缀. 如果不存在公共前缀,返回空字符串 "". 示例 1: 输入: ["flower","flow ...

  2. python编写自定义函数计算一维numpy数组中与指定目标数值最接近(距离最近)的数值(find closest value in numpy array to a certain value)

    python编写自定义函数计算一维numpy数组中与指定目标数值最接近(距离最近)的数值(find closest value in numpy array to a certain value) 目 ...

  3. 请编写一个函数,接收两颗星星赤经和赤纬的角度作为参数,计算并返回这两颗星星所对弧的角度。

    [问题描述] 给定两颗星星的赤经和赤纬的角度 (a1, d1)和(a2, d2) 它们所对弧的角度计算公式为: 赤经a1和a2是 -180o~ 180o 之间的角,a=a2-a1 赤纬d1和d2是 - ...

  4. 求行指针所指的字符串数组中长度最长的字符串所在的行下标

    <程序设计基础-c语言>杨莉 刘鸿翔 ISBN-978-7-03-032903-5 p137 习题5 3.行指针ss所指字符串数组中共有M个字符串,且字符串长度<N.求ss所指字符串 ...

  5. 怎样设置一个函数C语言,C语言中怎样编写一个函数 如何在C语言中定义一个函数?...

    如何在C语言中定义一个函数?小编很想在你面前流泪最后却还是选择装作打个哈欠 为什么小编怎么定义函数都不正确呢? 总是说小编 表达语法错误在main函数中 小编们可以在头文件与main函数之间定义,并编 ...

  6. 用Java编辑员工信息_编写一个函数来显示基于Oracle中特定部门的员工信息?

    这些是我创建的表的列表,并为创建的表插入值: CREATE TABLE DEPARTMENT (DEPARTMENT_ID NUMBER PRIMARY KEY, DEPARTMENT_NAME VA ...

  7. JS编写一个函数,实现传入一个不定长度字符串,查找出重复次数前n名的字符并分别统计其次数

    编写一个函数,实现传入一个不定长度字符串,查找出重复次数前n名的字符并分别统计其重复次数.写得好像比较复杂,大家有更好的方法欢迎留言指导,谢谢. function compare(string, n) ...

  8. 4.请编写一个函数void fun(char *tt,int pp[]),统计在tt字符串中“a”到“z”26个字母各自出现的次数,并依次放在pp所指数组中。

    4.请编写一个函数void fun(char *tt,int pp[]),统计在tt字符串中"a"到"z"26个字母各自出现的次数,并依次放在pp所指数组中. ...

  9. C语言编程>第十一周 ⑤ 请编写一个函数,用来删除字符串中的所有空格。

    例题:请编写一个函数,用来删除字符串中的所有空格. 例如,输入we l come,则输出为welcome. 请勿改动主函数main与其它函数中的任何内容,仅在函数fun的花括号中填入所编写的若干语句. ...

最新文章

  1. vmware虚拟机启动centOs黑屏
  2. 收藏 | YOLO系列综述:从V1到V4
  3. 架设国外服务器怎么维护,关于架设海外服务器这些事情你了解吗
  4. leetcode算法题--唯一元素的和
  5. 冲刺第八天 12.4 TUE
  6. 跟我一起学Redis之Redis配置文件啃了一遍之后,从尴尬变得有底气了(总结了一张思维图)...
  7. 10.15 lzxkj
  8. 在linux搭性能测试环境,性能测试学习第七天-----JMeter之linux环境部署篇
  9. pythonclass全局变量_python类怎么定义全局变量
  10. 解决Rails找不到Javascript的错误
  11. bug篇——MySQL的时区问题
  12. Linux 重启命令
  13. html5拼图微信小游戏,微信小程序:拼图游戏
  14. Power BI 数据分析可视化软件入门教程
  15. Cobal Strike免杀过360
  16. win10启动修复_高手教你怎样在Win10上修复主引导记录(MBR),轻松解决启动故障...
  17. c语言万年历方案论证,C语言编写方案-万年历分析.doc
  18. w7无法訪问计算机上硬盘分区,Win7/win10双系统无法打开磁盘分区提示拒绝访问怎么解决...
  19. 打了两分钟国际长途,我又得给手机充话费了
  20. Python 入门-Task1 变量、运算符、数据类型及位运算

热门文章

  1. tomcat发布solr服务出现404
  2. 国际标准时间(前台)和年月日时差为8个小时,如果使用String得到的日期会少八小时
  3. Bellhop 从入门到上手
  4. 汪子熙趣味成语接龙游戏的设计初衷
  5. 关于Assembly.CreateInstance()与Activator.CreateInstance()方法
  6. photoshop对图片批量处理操作
  7. 索尼摄像机MTS视频文件片段碎片恢复无缝组合修复技术
  8. 380v pcb 接线端子_什么是PCB接线端子
  9. 目前流行的计算机硬盘容量多少,电脑硬盘买什么容量的性价比最高?
  10. 十六、Android数据库操作