乘风破浪: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. jsp tomcat jdk版本对应

    jsp使用jdk8时,需要tomcat7以及以上版本,jsp在使用jdk7的时候,tomcat使用tomcat6即可

  2. C#(winform)为button添加背景图片,并去掉各种边框

    1.既然是添加背景图片 所以这里应该使用 Button.BackgroudImage = "" ;来设置图片 而不应该使用  Button.Image = "" ...

  3. System.Transactions事务超时设置

    System.Transactions 有2个超时属性(timeout 与 maxTimeout),可以通过配置文件来进行设置. 1. timeout System.Transactions 默认的t ...

  4. webstorm中es6语法报错,.vue文件中es6语法报错

    1.webstorm中es6语法报错,解决方法: 打开 Settings => Languages & Frameworks => Javascript把 Javascript L ...

  5. [转]OPEN(SAP) UI5 学习入门系列之一:扫盲与热身(上)

    本文转自:http://www.cnblogs.com/qianmarv/p/4671394.html 1 扫盲 什么是SAP Fiori? 了解SAP UI5必须要从SAP Fiori开始,两者概念 ...

  6. 字符编码unicode,utf-8和ascii

    Ascii编码 由于计算机是美国人发明的,因此,最早只有127个字符被编码到计算机里,也就是大小写英文字母.数字和一些符号,这个编码表被称为ASCII编码,比如大写字母A的编码是65,小写字母z的编码 ...

  7. Sping框架初步使用1

    Spring核心容器的理论:Spring核心容器就是一个超大工厂,所有的对象都会被当成Spring容器的核心管理对象,Spring把容器中一切对象统称为Bean(只要是一个Java类,Spring就可 ...

  8. JSON 教程

    1JSON 1.什么是 JSON ? 1.1JSON:JavaScript 对象表示法(JavaScript Object Notation). 1.2JSON 是存储和交换文本信息的语法.类似 XM ...

  9. php分页实例及其原理

    Part1:实例 /** * 取得上次的过滤条件 * @param string $param_str 参数字符串,由list函数的参数组成 * @return 如果有,返回array('filter ...

  10. H5演示文稿快速制作

    详见: http://www.geekfan.net/8107/ 或 http://www.jianshu.com/p/09a3bbb8b362