演算法之字串——最長公共字首

it_was發表於2020-09-29

難度 簡單:smirk:

編寫一個函式來查詢字串陣列中的最長公共字首。
如果不存在公共字首,返回空字串 ""

示例 1:
輸入: [“flower”,”flow”,”flight”]
輸出: “fl”

示例 2:
輸入: [“dog”,”racecar”,”car”]
輸出: “”
解釋: 輸入不存在公共字首。

:person_frowning:一開始的思路很簡單,就是單純的遍歷所有字串,兩兩比較,不斷更新最長公共字首的下標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;
    }

資料結構與演算法——字串

:raising_hand:這推薦一個評論的思路

  • 透過字串中字典序的比較,找到字典序最大和最小的兩個字串,這兩者的公共字首就是最長的公共字首!!!時間複雜度為O(n + min(max.length,min.length)):boom:
  • 即也可以透過將陣列排序,找到首尾這兩個字典序最小和最大的字串,看看兩者的差異即可!!這樣時間複雜比較高,為O(n * log(n) + min(max.length,min.length)):boom:

兩者的原理是一樣的,都是為了找到字典序最大和最小的字串!(關於時間複雜度這裡忽略字典序比較上的開銷)

程式碼如下
:eyes: :eyes: :eyes:

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 協議》,轉載必須註明作者和本文連結

相關文章