[英]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.