14. 最长公共前缀
思路:编写一个函数来查找字符串数组中的最长公共前缀。如果不存在公共前缀,返回空字符串 “”。
输入: ["flower","flow","flight"]
输出: "fl"
我首先想到的就是先取第一个字符串作为基准,然后再创建一个整数数组(长度和第一个字符串一样长),然后用其他几个字符串和他相比较(相同的字符则在对应位置加1),后来一想发现不仅太麻烦,而且逻辑不严密。->
实际上我们并不需要一个额外的数组,直接将其他的字符串和第一个字符串相比较接可以了,怎么比较呢?不断地判断第二个字符串的前缀是不是第一个字符串的前缀,但是为了找到最大的前缀,我们应该从第二个字符串的最长长度开始比较(不符合再不断地缩小长度直到满足)。
->
那我们如何判断该前缀是否存在呢?indexOf()这个方法派上了用场,只要该结果返回0,证明该字符串就是前缀(因为从0开始匹配了)。
完整代码如下:
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) {//等于0就是存在公共部分
prefix = prefix.substring(0, prefix.length() - 1);//每次长度减少并判断是否是公共部分
if (prefix.isEmpty()) return "";//直到减少到字符串为空还没有公共就返回空
}
return prefix;
}
还有就是使用前缀树,用count记录经过此路径的单词数量:
class Solution {
public String longestCommonPrefix(String[] strs) {
if(strs.length == 0) return "";
if(strs.length == 1) return strs[0];
Tire tire = new Tire();
for (String str : strs) {
if (str.length() == 0) {
return "";
}
tire.insert(str);
}
return tire.searchMaxPrefix(strs[0],strs.length);
}
class Tire {
class TireNode {
TireNode[] child;
boolean flag;
int count;
public TireNode() {
child = new TireNode[26];
flag = false;
count = 0;
}
}
/** 前缀树的根节点 */
TireNode root;
public Tire() {
root = new TireNode();
}
/**
* 插入每一个单词进入前缀树
* @param str
*/
public void insert(String str) {
TireNode cur = root;
cur.count++;
for (int i = 0; i < str.length(); i++) {
if (cur.child[str.charAt(i) - 'a'] == null) {
cur.child[str.charAt(i) - 'a'] = new TireNode();
}
cur = cur.child[str.charAt(i) - 'a'];
cur.count++;
}
cur.flag = true;
}
/**
* 查找最长公共前缀
* @return
*/
public String searchMaxPrefix(String s,int len) {
StringBuilder sb = new StringBuilder();
TireNode cur = root;
for(int i = 0;i < s.length(); i++){
//if(cur.count < len) break;
if (cur.child[s.charAt(i) - 'a'].count == len) {
sb.append(s.charAt(i));
cur = cur.child[s.charAt(i) - 'a'];
}else{
return sb.toString();
}
}
return sb.toString();
}
}
}
不知道为啥,写的时候老是忘记cur = cur.child[s.charAt(i) - ‘a’];这句,下不为例!!