繁体   English   中英

最长回文查找算法的时间复杂度

[英]Time complexity of longest palindrome finding algorithm

有人可以帮我解决这个算法的时间复杂度吗? 找到最长的回文 substring ( https://leetcode.com/problems/longest-palindromic-substring/ ) 是一个 leetcode 任务。 我相信这是 O(n³),但如何计算呢? 我的方法是:for 循环进行 s.length 次(称为n ),内部循环,在字符串由相等字符组成的更坏情况下,将扩展 window n 次,因此 O(n²)。 但是工作时间对于 O(n^2) 来说似乎太大了。 这是代码:

public String longestPalindrome(String s) {
    if (s.length() == 1) {
        return s;
    }
    String max = "";
    
    for (int i = 0; i < s.length() - 1; i++) {
        int lpointer = i;
        int rpointer = i + 1;
        while (rpointer < i + 3) {
            int t = rpointer;
            System.out.println(lpointer + " " + rpointer);
            while (lpointer >= 0 && rpointer < s.length() && s.charAt(lpointer) == s.charAt(rpointer)) {
                lpointer--;
                rpointer++;
            }
            
            String temp = s.substring(lpointer + 1, rpointer);
            max = max.length() < temp.length() ? temp : max;
            rpointer = t + 1;
            lpointer = i;
            if (rpointer == s.length()) {
                break;
            }
        }
    }
    
    return max == "" ? String.valueOf(s.charAt(0)) : max;
}

非常感谢任何帮助!

我会说你的算法是 O(n²) 即使你有三个循环:

for 循环的时间复杂度非常简单:您对n长字符串进行了n次迭代。 内部 while 循环有点复杂:我注意到在内部 while 循环之外,两个光标总是与12不同。 我想那是因为您想检查均匀和不均匀的回文。 这意味着对于 for 循环的每次迭代,内部 while 循环只运行两次。 此外,内部 while 循环最多可以运行字符串长度的一半,因为它在两个方向上进行搜索。 这导致两个 while 循环的复杂度都为2 * n/2 ,等于n 所以n*n导致 O(n²)。

尽管如此,除了时间复杂性之外,与平均提交相比,您的代码运行速度非常慢( >700 毫秒)。 通过一些优化,我能够以仅15 毫秒的运行时间重现 O(n²) 算法。 它几乎使用了您的尝试。 唯一的主要区别是,它没有使用两个内部 while 循环来区分偶数和奇数,而是使用了两个不同的独立循环:

public static String longestPalindrome(String s) {
    if (s.length() <= 0) return "";
    char[] chars = s.toCharArray();
    int longest = 0;
    int iLongest = 0;
    for (int i = 0; i < chars.length; i++) { //position to start from 
        if (longest == chars.length || (chars.length - 1 == longest && ((chars.length % 2 != 0 && longest % 2 == 0) || i - 1 > longest / 2))) break; //skip useless iterations
        //uneven
        for (int j = 0; j <= (chars.length - 1 - i < i ? chars.length - 1 - i : i); j++) { //max length possible in both directions
            if (chars[i+j] == chars[i-j]) {
                int nLongest = j*2+1;
                if (nLongest > longest) {
                    longest = nLongest;
                    iLongest = i;
                }
            } else break;
        }
        //even
        for (int j = 0; j <= (chars.length - 1 - i < i ? chars.length - 1 - i : i - 1); j++) {
            if (chars[i+j] == chars[i-j-1]) {
                int nLongest = (j+1)*2;
                if (nLongest > longest) {
                    longest = nLongest;
                    iLongest = i;
                }
            } else break;
        }
    }
    int start = iLongest - ((longest % 2 == 0 ? longest : longest - 1) / 2);
    int stop = iLongest + ((longest - 1) / 2);
    return s.substring(start, stop + 1);
}

希望这能回答您的问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM