[英]Parentheses change O(n) algorithm
如果我有一个n
开的长度的字符串(
闭)
括号,我都数不过来我改变收盘时的数)
括号打开(
每次当我有比开一个在当前时刻在遍历右括号在该字符串的每个子字符串中从左到右。
例如:n = 3, s = ) ( )
:
s 的所有子串都是[ ), ) (, ) ( ), (, ( ), ) ]
我们将不得不计算所有子字符串,就像在) ( )
我们有 close = 1 和 open = 0,close > open 因此计数++。 现在当前处理的字符串是( ( )
,没有更多的变化要做。同样,当我们对所有子字符串执行此操作时,计数将为 4。
我写了一个蛮力代码。 我假设有没有办法使用堆栈或动态编程在 O(n) 或其他东西中做到这一点?
我的蛮力就像: 1. 创建给定字符串的每个子字符串。 O(n^2)。 2. 一次迭代一个子串以计算变化。 O(n) 因此,总复杂度为 O(n^3)
O 注释没有考虑诸如簿记/状态变量等。它只与输入数据的处理频率有关。 如果我理解你的任务是正确的,你只需要在每个角色中循环一次。 由于在该单次循环期间,您没有可用的信息来告诉您有关该行后面字符的一些信息,因此您绝对别无选择,只能一次遍历整个字符串。 因此 O(N) 是此任务的最佳可能复杂度。
如果你的“蛮力代码”循环不止一次(也就是不是 O(N)),把它贴在这里,人们会看的。
这个问题可以通过做一些预计算在 O(n^2) 中解决。 左右取两个大小为 n(字符串长度)的数组。 left[index] 将存储从 s[0] 到 s[index] 的左括号 no,同样 right 将存储右括号 no。 因此,对于您的示例s = ")()"
,左侧将是 [0, 1, 1],右侧将是 [1, 1, 2]。 这种预计算可以在 O(n) 中完成。 现在我们需要计算每个区间 (i,j) 应该添加多少个左括号。 因此,对于每个间隔并将它们相加。 对于每个区间,使用 O(1) 中的预计算数组计算出这个值。 要迭代每个间隔,我们需要 O(n^2)。 所以整体复杂度是 O(n^2)。
int main(){
vector<int>prefix_sum_left_parentheisis(1000, 0);
vector<int>prefix_sum_right_parentheisis(1000, 0);
string s = ")()";
int count_left_parenthesis = 0;
int count_right_parenthesis = 0;
int index = 0;
for(auto ch:s) {
if(ch=='(')
count_left_parenthesis++;
else
count_right_parenthesis++;
prefix_sum_left_parentheisis[index] = count_left_parenthesis;
prefix_sum_right_parentheisis[index] = count_right_parenthesis;
index++;
}
auto total = 0;
for(auto i = 0; i < s.size(); i++) {
for(auto j = i; j < s.size(); j++) {
if(i == 0) {
total += max(0, prefix_sum_right_parentheisis[j] - prefix_sum_left_parentheisis[j]);
}
else {
auto count_left_parenthesis_in_range = prefix_sum_left_parentheisis[j] - prefix_sum_left_parentheisis[i-1];
auto count_right_parenthesis_in_range = prefix_sum_right_parentheisis[j] - prefix_sum_right_parentheisis[i-1];
total += max(0,count_right_parenthesis_in_range - count_left_parenthesis_in_range);
}
}
}
cout << "answer is: " << total;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.