乘风破浪: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. Struts2 resulttype

    本文章只介绍较为常用的三种result type 1.dispatcher 2.redirect 3.redirectAction 一.dispatcher 用于转向JSP页面,这个是默认的结果类型, ...

  2. Debian 9 启动后进入命令行

    打开 default grub 配置 $ sudo vi /etc/default/grub 修改以下3处内容 1. 找到行 GRUB_CMDLINE_LINUX_DEFAULT="quie ...

  3. vs2015 点击cshtml 后提示 "无效指针" 的解决办法

    1. 关闭vs 2. 删除 %LocalAppData%\Microsoft\VisualStudio\14.0\ComponentModelCache 3. 打开vs OK 解决

  4. spring security认证

    1 开发基于表单的认证 Spring security核心的功能 认证(你是谁?) 授权(你能干什么?) 攻击防护(防止伪造身份) spring security实现了默认的用户名+密码认证,默认用户 ...

  5. MVC知识点

    一·  MVC MVC设计模式->MVC框架(前端开发框架),asp.net(webform) aspx M:Model (模型,负责业务逻辑处理,比如说去db中获取数据) V:View (视图 ...

  6. 线程不安全的类不要轻易做为static变量使用,及如何使用ThreadLocal将共享变量变为独享变量

    参考原文:<关于SimpleDateFormat安全的时间格式化线程安全问题>

  7. BZOJ P1212 [HNOI2004] L语言

    标点符号的出现晚于文字的出现,所以以前的语言都是没有标点的.现在你要处理的就是一段没有标点的文章. 一段文章T是由若干小写字母构成.一个单词W也是由若干小写字母构成.一个字典D是若干个单词的集合. 我 ...

  8. 原生Ajax(XMLHttpRequest)

    一.什么是Ajax: 全称Asynchronous JavaScript and XML: 异步的 JavaScript 和 XML: 可以在不重新加载整个页面的情况下(偷偷发数据),与服务器交换数据 ...

  9. 关于<!DOCTYPE html>

    1.定义 DOCTYPE标签是一种标准通用标记语言的文档类型声明,目的是要告诉标准通用标记语言解析器,它应该使用什么样的文档类型定义(DTD)来解析文档. <!DOCTYPE> 声明必须是 ...

  10. javascript 获取服务时间

    用到了jquery的ajax方法,ajax自己写也可以. 具体用法 var setId = setInterval(function(){ var xhr = $.ajax({ type: 'HEAD ...