英文:
Longest Palindrome Substring (LeetCode) solution using expandAroundCenter function, how isn't O(n^3)?
问题
代码部分不要翻译,只返回翻译好的内容:
如何不是O(n^3),因为在每个for循环内部,我们有两个while循环,一个用于len1,另一个用于len2?
下面的解决方案可以正确找到回文。但是我感到困惑。
这是来自LeetCode的解决方案:
public String longestPalindrome(String s) {
if (s == null || s.length() < 1) return "";
int start = 0, end = 0;
//循环1
for (int i = 0; i < s.length(); i++) {
//循环2
int len1 = expandAroundCenter(s, i, i);
//循环3
int len2 = expandAroundCenter(s, i, i + 1);
int len = Math.max(len1, len2);
if (len > end - start) {
start = i - (len - 1) / 2;
end = i + len / 2;
}
}
return s.substring(start, end + 1);
}
private int expandAroundCenter(String s, int left, int right) {
int L = left, R = right;
while (L >= 0 && R < s.length() && s.charAt(L) == s.charAt(R)) {
L--;
R++;
}
return R - L - 1;
}
有什么想法吗?
英文:
How it's not O(n^3) since inside each for loop we do 2 while loops one for len1 and other for len2 ?
The below solution is working outputs the palindrome correctly. But I am confused.
Here is the solution from LeetCode:
public String longestPalindrome(String s) {
if (s == null || s.length() < 1) return "";
int start = 0, end = 0;
//Loop 1
for (int i = 0; i < s.length(); i++) {
//Loop 2
int len1 = expandAroundCenter(s, i, i);
//Loop 3
int len2 = expandAroundCenter(s, i, i + 1);
int len = Math.max(len1, len2);
if (len > end - start) {
start = i - (len - 1) / 2;
end = i + len / 2;
}
}
return s.substring(start, end + 1);
}
private int expandAroundCenter(String s, int left, int right) {
int L = left, R = right;
while (L >= 0 && R < s.length() && s.charAt(L) == s.charAt(R)) {
L--;
R++;
}
return R - L - 1;
}
Any idea ?
答案1
得分: 1
你可能会对expandAroundCenter
运行两次感到困惑。
expandAroundCenter
函数的时间复杂度是O(n)。虽然它被运行了两次,但是它是按顺序运行的。因此,时间复杂度是O(2n),而不是O(n^2)。
由于expandAroundCenter
函数在一个for循环内被调用:
T(n) = n x 2n = 2n^2
因此,时间复杂度为O(n^2)。
英文:
You might have got confused with expandAroundCenter
running twice.
expandAroundCenter
function is O(n). It is being run twice but, it is being run in sequence. So it is like O(2n) rather than O(n^2).
And as expandAroundCenter function is being called inside a for loop :
T(n) = n x 2n = 2n^2
So, time complexity is O(n^2).
答案2
得分: 0
以下是翻译好的内容:
参数的解释很直接:
- 外部循环是
∈ O(n)
- 两个内部循环(对
expandAroundCenter(...)
的调用)按顺序运行,而不是嵌套的。因此,它们的复杂性可以相加- 对于内部循环,最坏情况是它从字符串的中心向外展开,即
left
和right
被设置为n/2
。在这种情况下,内部循环最多可以迭代n/2
次,因为要么left < 0
,要么right >= n
。因此,内部循环的复杂性是∈ O(n)
- 对于内部循环,最坏情况是它从字符串的中心向外展开,即
总体而言,我们得到 O(n) (外部循环) * 2 * O(n) (按顺序运行的内部循环) ∈ O(n^2)
关于代码的一些备注:
-
虽然可以,但在 Java 中一行中声明多个变量是不寻常的。因此
int start = 0, end = 0;
应改为
int start = 0; int end = 0;
此更改仅影响代码样式选择,不影响字节码。有关详细信息,请参见此帖子。
-
绝不能省略单行语句周围的可选大括号。如果以后想要添加一行并忘记包含所需的大括号,则可能会产生严重错误。因此
if (s == null || s.length() < 1) return "";
应重新编写为
if (s == null || s.length() < 1) { return ""; }
-
变量名应始终以小写字母开头(
L
->l
,R
->r
)。 -
变量应具有有意义的名称。
l
和r
并不真正具有意义。因此,我建议进行以下重构:- 将参数
left
和right
重命名为leftStart
和rightStart
- 将参数
l
和r
重命名为currentLeft
和currentRight
- 将参数
英文:
The argument is quite straight forward:
- the outer loop is
∈ O(n)
- the two inner loops (calls to
expandAroundCenter(...)
) run in sequence, not nested. Thus, their complexity can be added up- for the inner loop, the worst-case scenario is that it expands from the center of the
String
outwards, i.e.left
andright
are set ton/2
. In this case, the inner loop can at most iteraten/2
-times since then eitherleft < 0
orright >= n
. Thus, overall the inner loop is∈ O(n)
- for the inner loop, the worst-case scenario is that it expands from the center of the
In total, we get O(n) (outer loop) * 2 * O(n) (inner loops in sequence) ∈ O(n^2)
Some remarks on the code:
-
While possible, it is unusual in java to declare more than one variable in one line. Thus
int start = 0, end = 0;
should be
int start = 0; int end = 0;
This change is only code style choice and has no effect on byte code. See this post for details.
-
optional braces around one-line statements should never be omitted. This can be a source of nasty bugs if we later on want to add a line and forget to include the the needed braces. Thus
if (s == null || s.length() < 1) return "";
should be re-written to
if (s == null || s.length() < 1) { return ""; }
-
variable names should alwasy start with a lowercase letter (
L
->l
,R
->r
). -
variables should have meaningful names.
l
andr
are not really meaningful. Thus I propose the following refactoring:- renaming parameters
left
andright
toleftStart
andrightStart
- renaming parameters
l
andr
tocurrentLeft
andcurrentRight
- renaming parameters
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论