串:Leetcode14-最长公共前缀

文章目录

    • 题目
    • 解法一(c++)
    • 解法二(C++)

题目

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

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

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

示例 2
输入: [“dog”,“racecar”,“car”]
输出: “”
解释: 输入不存在公共前缀。

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/longest-common-prefix

解法一(c++)

最先想到的思路就是一个个接着比较,比如有三个字符串a,b,c,先找到a和b的最长公共前缀s1,再找到s1和c的最长公共前缀。

string longestCommonPrefix(vector<string>& strs) {
        if(strs.empty())    return "";	// 如果为空
        if(strs.size()==1)  return strs[0];	//如果只有一个字符串
        int len=strs[0].size();
        for(int i=1; i<strs.size(); i++){
            while(strs[i].substr(0,len)!=strs[0].substr(0,len)) len--;
        }
        return strs[0].substr(0,len);
    }

说明: vector< string> strs是一个字符串数组,每个vector就是一个字符串。以strs[0]为对比标准,然后找到最长的公共前缀长度len。

时间复杂度:
时间复杂度:O(N + m),其中N是strs数组的长度,m是strs[0]第一个字符串的长度。
空间复杂度:O(1)。

解法二(C++)

使用Trie(前缀树)来解决这类问题,其实这个题目用Trie有点大材小用了,不过也是一个方向。关于Trie的详细解答,可以看我的另一篇博客:Trie(字典树)详解与C++实现

class Trie{
public:
    bool flag=false;
    int size =0;
    Trie * next[26]={nullptr};
    Trie(){}
    void insert(string word){
        Trie * node = this;
        for(int i=0; i<word.length(); i++){
            char c = word[i];
            if(node->next[c-'a']==nullptr){
                node->size += 1;
                node->next[c-'a']=new Trie();
            }
            if(node->flag==true) break;
            node = node->next[c-'a'];
        }
        node->flag=true;
    }
};

using namespace std;
class Solution {
public:
    string longestCommonPrefix(vector<string>& strs) {
        if(strs.empty()) return "";
        Trie * root = new Trie();
        Trie * q;
        for(int i=0; i<strs.size(); i++){
            q = root;
            if(strs[i]=="") return"";
            q->insert(strs[i]);
        }
        int k=0;
        q = root;
        string res;
        while(q && q->size==1 && q->flag!=true){
            res = res + strs[0][k];
            char c = strs[0][k];
            q = q->next[c-'a'];
            k++;
        }
        return res;
    }
};

说明:
这个题目在前缀树的思想上,做了一些改进。用了一个额外的int类型的size保存分支数。并且在插入时,如果当前的节点已经是某个单词的尾结点了(node->flag=ture),就不用再继续插入了,因为这个题目需要的只是最长公共前缀。并且,如果检测到空字符串,直接return “”
在查找最长公共前缀的时候,我们任意选一个子串作为参考,从根节点开始查找,如果size分支数不为1,表明此节点往后已无公共前缀。如果该节点不为空,并且也不为单词的尾结点,分支数也为1,就输入公共前缀的一部分,并指向下一个字符链接。


复杂度分析
时间复杂度:O(N*M)主要是浪费在插入上,N个单词,M为最短长度。
空间复杂度:O©,C为第一单词的长度。

建议这个题目还是不要用Trie来做,太麻烦了,而且效率也不算高,等到后期再来补充其他的做法(分治等)。

你可能感兴趣的:(今天刷题了吗,-,数组&字符串)