[英]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 循环之外,两个光标总是与1
或2
不同。 我想那是因为您想检查均匀和不均匀的回文。 这意味着对于 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.