腾讯精选练习题31、最长公共前缀

189 篇文章 0 订阅
162 篇文章 0 订阅

 

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

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

示例 1:

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

示例 2:

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

说明:

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

 

方法一、

class Solution {
    public String longestCommonPrefix(String[] strs) {
     
        if(strs.length==0||strs[0].length()==0)
            return "";
        
           String res=strs[0];
        for(int i=1;i<strs.length;i++){
            int l=0;
             while(l<res.length()&&l<strs[i].length()&&res.length()>0){
                 if(res.charAt(l)!=strs[i].charAt(l)){
                     res=res.substring(0,l);
                     continue;
                 }
                  
                 l++;
             }
            res=res.substring(0,l>res.length()?res.length():l);
        }
       
        return res;
    }
}

 

 

方法二、

水平扫描法

时间复杂度:O(S),S是所有字符串中字符数量的总和。

最坏的情况下,n个字符串都是相同的。算法会将S1与其它字符串[S2....Sn]都做一次比较。这样就会进行S次字符比较,其中S是输入数据中所有的字符数量。

空间复杂度:O(1),我们只需要使用常数级别的额外空间。

class Solution {
    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) {
            prefix = prefix.substring(0, prefix.length() - 1);
            if (prefix.isEmpty()) return "";
        }        
    return prefix;
    }
}

 

 

方法三、

分治

思路

这个算法的思路来自于LCP操作的结合律。 我们可以发现: LCP(S1…Sn)=LCP(LCP(S1…Sk),LCP(Sk+1…Sn))LCP(S_1 \ldots S_n) = LCP(LCP(S_1 \ldots S_k), LCP (S_{k+1} \ldots S_n))LCP(S1​…Sn​)=LCP(LCP(S1​…Sk​),LCP(Sk+1​…Sn​)) ,其中 LCP(S1…Sn)LCP(S_1 \ldots S_n)LCP(S1​…Sn​) 是字符串 [S1…Sn][S_1 \ldots S_n][S1​…Sn​] 的最长公共前缀,1<k<n1 < k < n1<k<n。

算法

为了应用上述的结论,我们使用分治的技巧,将原问题 LCP(Si⋯Sj)LCP(S_i\cdots S_j)LCP(Si​⋯Sj​) 分成两个子问题 LCP(Si⋯Smid)LCP(S_i\cdots S_{mid})LCP(Si​⋯Smid​) 与 LCP(Smid+1,Sj)LCP(S_{mid+1}, S_j)LCP(Smid+1​,Sj​) ,其中 mid=i+j2\frac{i+j}{2}2i+j​。 我们用子问题的解 lcpLeftlcpRight 构造原问题的解 LCP(Si⋯Sj)LCP(S_i \cdots S_j)LCP(Si​⋯Sj​)。 从头到尾挨个比较 lcpLeftlcpRight 中的字符,直到不能再匹配为止。 计算所得的 lcpLeftlcpRight 最长公共前缀就是原问题的解 LCP(Si⋯Sj)LCP(S_i\cdots S_j)LCP(Si​⋯Sj​)

复杂度分析:

最坏的情况下,我们有n个长度为m的相同字符串。

时间复杂度:O(S),S是所有字符串中字符数量的总和 S=m*n.

时间复杂度的递推式为T(n)=2*T(n/2)+O(m),化简后可知是O(S).最好情况下,算法会进行minLen*n次比较其中minLen是数组中最短字符串的长度。

空间复杂度:O(m*log(n)).内存开支主要是递归过程中使用的栈空间所消耗的。一共会进行log(n)次递归,每次需要m的空间存储返回结果,所以空间复杂度为O(m*log(n))

class Solution {
    public String longestCommonPrefix(String[] strs) {
        if(strs.length==0)
            return "";
        
        return getLongestCommonPrefix(strs,0,strs.length-1);
    }
    
    private String getLongestCommonPrefix(String[]strs,int l,int r){
       
        if(l==r){
           return strs[l];
        }
         int mid=l+(r-l)/2;
        //[0,mid] [mid+1,r]
        String left=getLongestCommonPrefix(strs,l,mid);
        String right=getLongestCommonPrefix(strs,mid+1,r);
        return commonPrefix(left,right);
    }
    
    private 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);
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值