You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何计算基于Trie实现的LeetCode最长公共前缀解法的时间复杂度

关于Trie解法解决最长公共前缀的时间复杂度纠正

我先梳理你的解法核心逻辑:通过构建Trie树统计每个节点的访问次数,找到所有字符串都经过的节点路径作为候选前缀,再筛选最长的那个。接下来纠正你时间复杂度分析里的不准确之处:

你的分析错误点纠正

  • 第88行(FindAllPrefixes方法):
    你认为是O(nm),这里的定义混乱了。实际这个方法里,每个字符串最多遍历到其最长公共前缀的长度(设为L,即最终结果的长度,最长不超过所有字符串中最短的长度),而非整个字符串长度。所以这部分的时间复杂度应该是**O(mL)**,其中m是字符串数组的元素个数,L是最长公共前缀的长度。

  • 第89行(排序前缀列表):
    你用了O(kj),但k其实就是m(每个字符串对应一个候选前缀),排序时比较的是前缀长度,每个比较操作是O(1)(仅比较长度数值),所以排序的时间复杂度是O(m log m),而非O(kj)。排序的时间主要由元素个数决定,字符串长度比较是常数时间。

  • 总复杂度计算错误:
    你错误地把各部分复杂度相乘了,但时间复杂度是取各部分的最大值(或相加后取主导项)。另外你遗漏了构建Trie的时间(第85-86行):构建Trie需要遍历所有字符串的每个字符,总共有S个字符(S是所有字符串的总长度),所以这部分是O(S)。

正确的总时间复杂度

把各部分的复杂度列出来:

  • 构建Trie:O(S),S是所有字符串的总字符数
  • 生成候选前缀列表:O(m*L),m是字符串数量,L是最长公共前缀长度
  • 排序前缀列表:O(m log m)
  • 验证前缀:O(m*L)

总复杂度由最大的项主导,所以最终时间复杂度是O(S + m log m)。因为S通常远大于m*L和m log m(比如当字符串很长但公共前缀很短时);如果所有字符串完全相同,S = m*L,此时总复杂度为O(m*L + m log m),依然可简化为O(S + m log m)。

另外补充:你的解法存在优化空间,比如FindAllPrefixes后不需要排序再验证——最长公共前缀是唯一的,你可以直接在Trie遍历过程中一次找到最长公共前缀,去掉O(m log m)的排序开销,进一步提升性能。

格式化后的代码

public class Solution
{
    public class TrieNode
    {
        public bool IsEndOfString = false;
        public TrieNode[]? Children;
        public int Visits = 0;
    }
    
    public class Trie
    {
        private const int AlphabetSize = 26;
        private TrieNode _root;
        private int _max = 0;
    
        public Trie()
        {
            _root = new TrieNode()
            {
                Visits = -1,
                Children = new TrieNode[AlphabetSize]
            };
        }
    
        public void Insert(string key)
        {
            TrieNode currentNode = _root;

            foreach (char c in key)
            {
                int currentIndex = c - 'a';
    
                if (currentNode.Children[currentIndex] is null)
                    currentNode.Children[currentIndex] = new TrieNode()
                    {
                        Children = new TrieNode[AlphabetSize]
                    };

                currentNode = currentNode.Children[currentIndex];

                currentNode.Visits++;
    
                if (currentNode.Visits > _max)
                    _max = currentNode.Visits;
            }
    
            currentNode.IsEndOfString = true;
        }
    
        public List<string> FindAllPrefixes(string[] strs)
        {
            StringBuilder prefixBuilder = new StringBuilder();
            List<string> listOfPrefixes = new List<string>();
        
            foreach (string key in strs)
            {
                TrieNode currentNode = _root;
        
                foreach (char c in key)
                {
                    var currentIndex = c - 'a';
                    if (currentNode.Children[currentIndex] is not null && currentNode.Children[currentIndex].Visits == _max)
                    {
                        prefixBuilder.Append((char) (currentIndex + 'a'));
                        currentNode = currentNode.Children[currentIndex];
                    }
                    else
                        break;
                }
                listOfPrefixes.Add(prefixBuilder.ToString());
                prefixBuilder.Clear();
            }

            return listOfPrefixes;
        }
    }

    public string LongestCommonPrefix(string[] strs)
    {
        if (strs.Length == 1)
            return strs[0];

        Trie trie = new Trie();

        foreach (string str in strs)
            trie.Insert(str);
        
        List<string> listOfPrefixes = trie.FindAllPrefixes(strs);
        listOfPrefixes.Sort((a, b) => b.Length.CompareTo(a.Length));
        string longestPrefix = listOfPrefixes[0];
        
        foreach (string str in strs)
        {
            if (!str.StartsWith(longestPrefix))
                return string.Empty;
        }

        return longestPrefix;
    }
}

内容的提问来源于stack exchange,提问作者iamhaitham

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 00:21:26