難度 簡單
編寫一個函式來查詢字串陣列中的最長公共字首。
如果不存在公共字首,返回空字串""
。
示例 1:
輸入: [“flower”,”flow”,”flight”]
輸出: “fl”
示例 2:
輸入: [“dog”,”racecar”,”car”]
輸出: “”
解釋: 輸入不存在公共字首。
一開始的思路很簡單,就是單純的遍歷所有字串,兩兩比較,不斷更新最長公共字首的下標index,可是這樣一來時間複雜度就很高為 O(N(陣列中所有字串的總長度))
public String longestCommonPrefix1(String[] strs) {
if(strs == null || strs.length == 0){
return "";
}
String max_Common = strs[0]; //初始最長為第一個元素
for(int i =1;i <strs.length;i++){ //然後max_common不斷和剩下的進行比較
int index = -1;
for(int j = 0;j < strs[i].length() && j < max_Common.length();j++){
if(strs[i].charAt(j) != max_Common.charAt(j)){
break;
}
index = j;
}
if(index == -1){ //沒有公共部分
return "";//直接返回就好了
}else{
max_Common = max_Common.substring(0,index); //這裡不斷更新max_common!!!
}
}
return max_Common;
}
這推薦一個評論的思路
- 透過字串中字典序的比較,找到字典序最大和最小的兩個字串,這兩者的公共字首就是最長的公共字首!!!時間複雜度為O(n + min(max.length,min.length))
- 即也可以透過將陣列排序,找到首尾這兩個字典序最小和最大的字串,看看兩者的差異即可!!這樣時間複雜比較高,為O(n * log(n) + min(max.length,min.length))
兩者的原理是一樣的,都是為了找到字典序最大和最小的字串!(關於時間複雜度這裡忽略字典序比較上的開銷)
程式碼如下
public String longestCommonPrefix(String[] strs) {
if(strs == null || strs.length == 0){
return "";
}
Arrays.sort(strs); //排序的話程式碼上比較簡潔
String min = strs[0]; //字典序最小
String max = strs[strs.length - 1];//字典序最大
String max = strs[0]; //不排序的話,可以單個比較,利用字串的compareTo函式
String min = strs[0];
for(int i = 1;i<strs.length;i++){
if(strs[i].compareTo(max) > 0){
max = strs[i];
}
if(strs[i].compareTo(min) < 0){
min = strs[i];
}
}
//----------------------以下過程都一樣-------------------------//
int index = -1;
for(int i = 0;i<min.length();i++){ //兩者的最大公共字首!
if(min.charAt(i) != max.charAt(i)){
break;
}
index = i;
}
if(index == -1){
return "";
}else{
return min.substring(0,index + 1);
}
}
嗯。。。。。。。看到字首這個字眼莫名的就能想到字首樹,給一個字首樹的實現程式碼
package ddx.september.day29;
import ddx.september.day28.Normal_31;
import java.util.Arrays;
public class Normal_14{
public static void main(String[] args){
Normal_14 demo = new Normal_14();
String s = demo.longestCommonPrefix(new String[]{"fl","flower","flo"});
System.out.println(s);
}
public String longestCommonPrefix(String[] strs) {
if (strs == null || strs.length == 0) {
return "";
}
Trie trie = new Trie();
for (String str : strs) {
trie.insert(str);
}
String max_common = "";
TrieNode cur = trie.root;
while (cur.count == 1 && cur.end == 0){
for (int i = 0; i < 26; i++) {
if (cur.map[i] != null) {
max_common += (char) (i + 'a');
cur = cur.map[i];
break;
}
}
}
return max_common;
}
}
class Trie {
public TrieNode root;
public Trie() {
this.root = new TrieNode();
}
//構造字首樹的插入方法
public void insert(String word) {
if (word == null) {
return;
}
char[] arr = word.toCharArray();
TrieNode node = root;
for (int i = 0; i < arr.length; i++) {
int cur = arr[i] - 'a';
if (node.map[cur] == null) {
node.map[cur] = new TrieNode();
node.count++;
}
node = node.map[cur]; //結點已經建立,繼續向下更新
node.path++; //結點數加一
}
node.end++;
}
}
//字首樹結點
class TrieNode {
int path; //公用這個節點的單詞數
int end; //以這個結點結束的單詞數
int count; //子結點的數量
public TrieNode[] map;
public TrieNode() {
this.end = 0;
this.path = 0;
this.count = 0;
this.map = new TrieNode[26];
}
}
本作品採用《CC 協議》,轉載必須註明作者和本文連結