乘风破浪:LeetCode真题_014_Longest Common Prefix

一、前言

如何输出最长的共同前缀呢,在给定的字符串中,我们可以通过笨办法去遍历,直到其中某一个字符不相等了,这样就得到了最长的前缀。那么还有没有别的办法呢?

二、Longest Common Prefix

2.1 问题

2.2 分析与解决

    由问题我们可以知道,所有的字符都是小写的,这样我们不需要纠结这一部分,其次就是如何设计一种算法来遍历了。我们可以先计算出字符串的最小长度,然后作为循环的次数 ,之后来对比和查看。当然我们还有其他的方法,比如横向的两个两个进行求集,最终得到结果,或者纵向的按照我们上面的方法去比较。或者用分治法,二分搜索法,甚至采用树状结构搜索法。

    下面我们看看官网的答案:

    横向搜索法:

class Solution {
public String longestCommonPrefix(String[] strs) {
if (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;
}
}

    我们可以看到是非常巧妙的,通过第一个和第二个相比,刚开始使用indexOf()不成功会产生-1,如果成功了并且显示起始位置为0这样才算通过,其中每一次都是前缀去除一个字符来和原来的进行索引:prefix = prefix.substring(0, prefix.length() - 1);,然后将比较产生的prefix再和后面的继续比较,直至比较完毕得到想要的结果。

  纵向搜索法:

class Solution {
public String longestCommonPrefix(String[] strs) {
if (strs == null || strs.length == 0) return "";
for (int i = 0; i < strs[0].length() ; i++){
char c = strs[0].charAt(i);
for (int j = 1; j < strs.length; j ++) {
if (i == strs[j].length() || strs[j].charAt(i) != c)
return strs[0].substring(0, i);
}
}
return strs[0];
}
}

其实也是我们上面讲的,只不过没有比较最短长度而已。

分治法,思路也很简单,两两合并加快合并的效率:

class Solution {
public String longestCommonPrefix(String[] strs) {
if (strs == null || strs.length == 0) return "";
return longestCommonPrefix(strs, 0 , strs.length - 1);
} private String longestCommonPrefix(String[] strs, int l, int r) {
if (l == r) {
return strs[l];
}
else {
int mid = (l + r)/2;
String lcpLeft = longestCommonPrefix(strs, l , mid);
String lcpRight = longestCommonPrefix(strs, mid + 1,r);
return commonPrefix(lcpLeft, lcpRight);
}
} String commonPrefix(String left,String right) {
int min = Math.min(left.length(), right.length());
for (int i = 0; i < min; i++) {
if ( left.charAt(i) != right.charAt(i) )
return left.substring(0, i);
}
return left.substring(0, min);
}
}

相信看了代码和图片都能理解要表达的意思。

  二分查找法:

class Solution {
public String longestCommonPrefix(String[] strs) {
if (strs == null || strs.length == 0)
return "";
int minLen = Integer.MAX_VALUE;
for (String str : strs)
minLen = Math.min(minLen, str.length());
int low = 1;
int high = minLen;
while (low <= high) {
int middle = (low + high) / 2;
if (isCommonPrefix(strs, middle))
low = middle + 1;
else
high = middle - 1;
}
return strs[0].substring(0, (low + high) / 2);
} private boolean isCommonPrefix(String[] strs, int len){
String str1 = strs[0].substring(0,len);
for (int i = 1; i < strs.length; i++)
if (!strs[i].startsWith(str1))
return false;
return true;
}
}

     通过找到最小的字符串长度,然后对所有的字符串按照这个长度进行二分查找,不断的细化下去,看看在细化的过程中是否有共同的前缀,最终返回结果。

我们的算法:

public class Solution {
/**
* 题目大意
* 写一个函数找出一个字串所数组中的最长的公共前缀。
*
* 解题思路
* 第一步先找出长度最小的字符串,然后将这个字符串与其它的字符串相比找出最短的最公共前缀。
*/
public String longestCommonPrefix(String[] strs) {
if (strs == null) {
return null;
} if (strs.length == 0) {
return "";
} int min = Integer.MAX_VALUE; // 记录最短的字符串的长度 // 找短字符串的长度
for (String str : strs) { if (str == null) {
return null;
} if (min > str.length()) {
min = str.length();
}
} int i; // 记录最长前缀的字符数
boolean flag;
for (i = 0; i < min; i++) {
flag = true;
for (int j = 1; j < strs.length; j++) {
if (strs[0].charAt(i) != strs[j].charAt(i)) {
flag = false;
break;
}
} if (!flag) {
break;
}
} return strs[0].substring(0, i);
}
}

     从下往上分别是上面几种算法的耗时情况,可以看到在这种情况下使用分治法和二分查找算法和其他算法基本上性能差不多。

三、总结

在这里我们更加明白了算法的意义和多样性,对于同一个问题从不同的角度思考就有不同的解答方式,这点是算法的迷人之处。

乘风破浪:LeetCode真题_014_Longest Common Prefix的更多相关文章

  1. 【算法】LeetCode算法题-Longest Common Prefix

    这是悦乐书的第146次更新,第148篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第5题(顺位题号是14),给定一个随机的字符串数组,查找这些字符串元素的公共前缀字符串, ...

  2. 乘风破浪:LeetCode真题_017_Letter Combinations of a Phone Number

    乘风破浪:LeetCode真题_017_Letter Combinations of a Phone Number 一.前言 如何让两个或者多个集合中的随机挑选的元素结合到一起,并且得到所有的可能呢? ...

  3. 乘风破浪:LeetCode真题_041_First Missing Positive

    乘风破浪:LeetCode真题_041_First Missing Positive 一.前言 这次的题目之所以说是难,其实还是在于对于某些空间和时间的限制. 二.First Missing Posi ...

  4. 乘风破浪:LeetCode真题_040_Combination Sum II

    乘风破浪:LeetCode真题_040_Combination Sum II 一.前言 这次和上次的区别是元素不能重复使用了,这也简单,每一次去掉使用过的元素即可. 二.Combination Sum ...

  5. 乘风破浪:LeetCode真题_039_Combination Sum

    乘风破浪:LeetCode真题_039_Combination Sum 一.前言     这一道题又是集合上面的问题,可以重复使用数字,来求得几个数之和等于目标. 二.Combination Sum ...

  6. 乘风破浪:LeetCode真题_038_Count and Say

    乘风破浪:LeetCode真题_038_Count and Say 一.前言     这一道题目,很类似于小学的问题,但是如果硬是要将输入和结果产生数值上的联系就会产生混乱了,因此我们要打破思维定势. ...

  7. 乘风破浪:LeetCode真题_037_Sudoku Solver

    乘风破浪:LeetCode真题_037_Sudoku Solver 一.前言 这次我们对于上次的模型做一个扩展并求解. 二.Sudoku Solver 2.1 问题 2.2 分析与解决     这道题 ...

  8. 乘风破浪:LeetCode真题_036_Valid Sudoku

    乘风破浪:LeetCode真题_036_Valid Sudoku 一.前言 有的时候对于一些基础知识的掌握,对我们是至关重要的,比如ASCII重要字符的表示,比如一些基本类型的长度. 二.Valid ...

  9. 乘风破浪:LeetCode真题_035_Search Insert Position

    乘风破浪:LeetCode真题_035_Search Insert Position 一.前言 这次的问题比较简单,也没有限制时间复杂度,但是要注意一些细节上的问题. 二.Search Insert ...

随机推荐

  1. cors允许的方法和contype-type

    https://fetch.spec.whatwg.org/#cors-safelisted-request-header get head post text/plain multipart/for ...

  2. 解决图片浮动调节不了的问题(使用vertical-align属性)

    vertical-align: middle; vertical-align 属性设置元素的垂直对齐方式. baseline  默认.元素放置在父元素的基线上.sub 垂直对齐文本的下标.super ...

  3. Linux笔记-Makefile伪指令解析

    本文是我在博客里面找到的,觉得对makefile的伪指令介绍得非常详细了!也提到了伪指令为何要用.PHONY:来声明!希望我的这篇转过来的文章能够帮助大家理解makefile的伪指令! 我的理解: 拿 ...

  4. 在ubuntu下使用visual studio code编写python

    感觉有了visual studio code之后,不管编写什么语言的代码都可以,简单安装对应的语言插件即可. 这不轮到了最近比较热的python语言,蹭着AI的热度,python语言成为了工程师们又一 ...

  5. [译]用R语言做挖掘数据《二》

    数据探索 一.实验说明 1. 环境登录 无需密码自动登录,系统用户名shiyanlou,密码shiyanlou 2. 环境介绍 本实验环境采用带桌面的Ubuntu Linux环境,实验中会用到程序: ...

  6. js的一些妙用

    在一个数组上  直接附加上另一个数组: Array.prototype.push.apply(array1, array2); 将对象转换成一个数组: Array.prototype.slice.ca ...

  7. API ,批量添加

    添加引用:cors using   system.web.http.cors API添加这句话:       [EnableCors("*", "*", &qu ...

  8. 浏览器获取正确的scrollTop值

    window.pageYOffset 被所有浏览器支持除了 IE 6, IE 7, IE 8, 不关doctype的事, 注IE9 开始支持此属性. window.scrollY 被Firefox, ...

  9. PHP高级工程师面试 - 笔试题

    Part1:HTTP协议 1.状态码的含义 1xx(临时响应) 表示临时响应并需要请求者继续执行操作的状态代码. 代码 说明 100 (继续) 请求者应当继续提出请求. 服务器返回此代码表示已收到请求 ...

  10. spring mybatis 关于 basepackage 和 mapperLocations 的通配符匹配实例

    SqlSessionFactoryBean mapperLocations 注意下面几点 classpath* mapperLocation 起始路径不能有 * ,如 dm* 就不行 ** list ...