1. 程式人生 > >LeetCode--14. Longest Common Prefix

LeetCode--14. Longest Common Prefix

題目連結:https://leetcode.com/problems/longest-common-prefix/

這是一個easy的題目,但是涉及的思維方式和方法還有一些用的比較少的高階資料結構都是值得討論研究的,意味深長。LeetCode的前兩百道題目各個都是經典,引人思考。這個題目要求一個字串集合的最長公共字首。

思路一:

一拿到題目的思路有兩個,其中一個是Trie樹,第二個就是這個實現起來相對快一些:最長公共字首長度n一定小於等於最短字串,然後逐個比較個字串中第i個(i<=n)字元是否相同即可,於是有了如下程式碼:

class Solution {
    public String longestCommonPrefix(String[] strs) {
        if(strs.length==0 || strs==null)
            return "";
        
        StringBuilder sb=new StringBuilder();
        int minLength=Integer.MAX_VALUE;
        
        for(int i=0;i<strs.length;i++)
            minLength=Math.min(minLength,strs[i].length());
        
        for(int j=0;j<minLength;j++)
        {
            char c =strs[0].charAt(j);
            int k=1;
            for(;k<strs.length;k++)
                if(c!=strs[k].charAt(j))
                    break;
            if(k<strs.length)
                break;
            sb.append(c);
        }
        return sb.toString();
    }
}

最壞時間複雜度為O(mn),空間複雜度為O(1),效能一般。

思路二:

先比較前兩個字串得到最長公共字首,再用的到的最長公共字首與後面的字串一一比較,從而得到最終的最長公共字首

程式碼很簡單,但是我覺得Solutions裡面的解法更優雅直接:

public String longestCommonPrefix1(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;
    }

思路三:

上述兩兩比較的方式(一趟複雜度為O(n))可以用歸併的思想進行優化(一趟複雜度為logn),歸併思想可以參考這兩篇:https://blog.csdn.net/To_be_to_thought/article/details/83994248https://blog.csdn.net/To_be_to_thought/article/details/83988767

程式碼如下:

public String longestCommonPrefix2(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);
    }

思路四:

字首樹這個思路是比較自然的思路,因為Trie樹就是為這個而設計的資料結構。將字串集合裡的字串建立在Trie樹上,然後數從根節點到第一個分叉節點經歷的邊數。未完待續!!!