zoukankan      html  css  js  c++  java
  • 简单-14-最长公共前缀

    编写一个函数来查找字符串数组中的最长公共前缀。

    如果不存在公共前缀,返回空字符串 ""。

    示例 1:

    输入: ["flower","flow","flight"]
    输出: "fl"
    示例 2:

    输入: ["dog","racecar","car"]
    输出: ""
    解释: 输入不存在公共前缀。
    说明:

    所有输入只包含小写字母 a-z 。

    横向扫描法(暴力):先取数组首位为目标值,再遍历其余数组元素,与目标值各个字符依次比较,遇到不等的比较下一个数组元素并更新目标值。

    class Solution {
        public String longestCommonPrefix(String[] strs) {
            if(strs.length==0)
                return "";
            StringBuilder res = new StringBuilder(strs[0]);
            for(int i=1; i<strs.length; i++){
                int j=0;
                for(; j<strs[i].length()&&j<res.length(); j++){
                    if(res.charAt(j)!=strs[i].charAt(j))
                        break;
                }
                res.delete(j,res.length());
                if(res.length()==0)
                    return "";
            }
            return res.substring(0);
        }
    }
    /*

    时间复杂度:O(mn)O(mn),其中 mm 是字符串数组中的字符串的平均长度,nn 是字符串的数量。最坏情况下,字符串数组中的每个字符串的每个字符都会被比较一次。

    
    

    空间复杂度:O(1)O(1)。使用的额外空间复杂度为常数。

    */
     

    纵向扫描法:从前往后依次遍历字符串的每一列,比较相同列的字符,直到某个字符达到长度上限或字符不等。

    class Solution {
        public String longestCommonPrefix(String[] strs) {
            if(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()||c!=strs[j].charAt(i))
                        return strs[0].substring(0,i);
                }
            }
            return strs[0];
        }
    }
    /*

    时间复杂度:O(mn)O(mn),其中 mm 是字符串数组中的字符串的平均长度,nn 是字符串的数量。最坏情况下,字符串数组中的每个字符串的每个字符都会被比较一次。

    
    

    空间复杂度:O(1)O(1)。使用的额外空间复杂度为常数。

    */
    
    

     分治法:递归思想,分别找出字符串数组前一半和后一半的公共前缀,再比较这两个字符串的公共前缀。

    class Solution {
        public String longestCommonPrefix(String[] strs) {
            if(strs.length==0)
                return "";
            return recursive(strs,0,strs.length-1);
        }
        public String recursive(String[]strs,int start,int end){
            if(start==end)
                return strs[start];
            int mid=(start+end)/2;
            String strLeft=recursive(strs,start,mid);
            String strRight=recursive(strs,mid+1,end);
            return commonPrefix(strLeft,strRight);
        }
        public String commonPrefix(String left, String right){
            for(int i=0; i<Math.min(left.length(),right.length()); i++){
                if(left.charAt(i)!=right.charAt(i))
                    return left.substring(0,i);
            }
            return left.length()<right.length()?left:right;
        }
    }
    /*

    时间复杂度:O(mn)O(mn),其中 mm 是字符串数组中的字符串的平均长度,nn 是字符串的数量。时间复杂度的递推式是 T(n)=2 cdot T(frac{n}{2})+O(m)T(n)=2⋅T(
    2
    n

    )+O(m),通过计算可得 T(n)=O(mn)T(n)=O(mn)。

    
    

    空间复杂度:O(m log n)O(mlogn),其中 mm 是字符串数组中的字符串的平均长度,nn 是字符串的数量。空间复杂度主要取决于递归调用的层数,层数最大为 log nlogn,每层需要 mm 的空间存储返回结果。

    */
     

    二分法:依旧是用目标值遍历数组的思想。不过重点在于快速找到前缀的末索引,先将索引缩小到最小的数组元素长度,再对该索引用二分查找,如果中间值是公共前缀,则目标值大于等于它,否则相反。

    该方法优化横向扫描法。

    class Solution {
        public String longestCommonPrefix(String[] strs) {
            if (strs == null || strs.length == 0) {
                return "";
            }
            int minLength = Integer.MAX_VALUE;
            for (String str : strs) {
                minLength = Math.min(minLength, str.length());
            }
            int low = 0, high = minLength;
            while (low < high) {
                int mid = (high - low + 1) / 2 + low;
                if (isCommonPrefix(strs, mid)) {
                    low = mid;
                } else {
                    high = mid - 1;
                }
            }
            return strs[0].substring(0, low);
        }
    
        public boolean isCommonPrefix(String[] strs, int length) {
            String str0 = strs[0].substring(0, length);
            int count = strs.length;
            for (int i = 1; i < count; i++) {
                String str = strs[i];
                for (int j = 0; j < length; j++) {
                    if (str0.charAt(j) != str.charAt(j)) {
                        return false;
                    }
                }
            }
            return true;
        }
    }
    /*

    时间复杂度:O(mn log m)O(mnlogm),其中 mm 是字符串数组中的字符串的最小长度,nn 是字符串的数量。二分查找的迭代执行次数是 O(log m)O(logm),每次迭代最多需要比较 mnmn 个字符,因此总时间复杂度是 O(mn log m)O(mnlogm)。

    
    

    空间复杂度:O(1)O(1)。使用的额外空间复杂度为常数。

    */
     

    排序后比较首尾元素  摘自该用户在题解下评论

    //计算复杂度应考虑排序字符串数组
    class
    Solution { public: string longestCommonPrefix(vector<string>& strs) { if(strs.empty()) return string(); sort(strs.begin(), strs.end()); string st = strs.front(), en = strs.back(); int i, num = min(st.size(), en.size()); for(i = 0; i < num && st[i] == en[i]; i ++); return string(st, 0, i); } };
  • 相关阅读:
    Angular——事件指令
    Angular——数据绑定
    Angular——自定义指令
    Angular——表单指令
    Angular——引入模板指令
    Angular——内置指令
    Angular——基本使用
    Canvas——基本入门
    JS高级——面向对象方式解决tab栏切换问题
    JS高级——面向对象方式解决歌曲管理问题
  • 原文地址:https://www.cnblogs.com/faded828x/p/13138614.html
Copyright © 2011-2022 走看看