15.最長連續不重複子序列
阿新 • • 發佈:2020-06-30
快排的劃分,歸併排序的歸併,之後的kmp都是雙指標演算法。
雙指標演算法的兩大類:
指向兩個區間或指向一個區間
雙指標演算法一般是這樣的
雙指標演算法運用了某些單調性質,可以將暴力的O(n^2)優化到O(n)
先來一個小的問題熱身,輸入一行若干個用空格隔開的單詞,然後依次每行輸出一個單詞。具體應用看這裡https://www.cnblogs.com/fx1998/p/12868788.html
1 #include <bits/stdc++.h> 2 using namespace std; 3 int main() { 4 char str[1010]; 5 cin.getline(str, 1010); 6 int len = strlen(str); 7 //cout << len << endl; 8 for (int i = 0; i < len; i++) { 9 int j = i; 10 //每一次i迴圈的時候,都保證i是指向單詞的第一個位置 11 while (j < len && str[j] != ' ') { //只要j沒有走到終點 12 //然後我們要找到當前這個單詞的最後一個位置 13 j++;14 } 15 //當while迴圈結束時,j就指向當前這個空格 16 //此時從i到j-1之間就是一個單詞 17 //這道題的具體邏輯 18 for (int k = i; k < j; k++) { 19 cout << str[k]; 20 } 21 cout << endl; 22 i = j; 23 //cout << j << endl; 24 } 25 return0; 26 }
本題的樣例解釋
答案是2 3 5
注意這裡說的連續是指位置連續
方法一:暴力做法
i是終點
j是起點
i - j + 1
方法二:雙指標演算法
紅顏色表示i
綠顏色表示j
j表示i往左最遠可以走多遠
然後發現性質:在i往右走的過程中,j不會往前走。是具有單調性的。
然後就可以優化了
我們只列舉i
j的話是每次看一下要不要往後走
如果有重複元素的話,就j++
一直移動到j和i之間沒有重複元素為止
所以最多是i走n步,j走n步,一共走2n步
時間複雜度從n^2優化到n
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int N = 100010; 4 int a[N], s[N]; 5 //a是原來的數 6 //s是每個數出現的次數 7 int main() { 8 int n; 9 cin >> n; 10 for (int i = 0; i < n; i++) { 11 cin >> a[i]; 12 } 13 int res = 0; //res表示答案 14 for (int i = 0, j = 0; i < n; i++) { 15 s[a[i]]++; //每次加入一個數 16 while (j <= i && s[a[i]] > 1) { //因為新加了一個數,然後有重複了,所以重複的一定是新加的數 17 s[a[j]]--; //把它拿出去 18 j++; 19 } 20 //while迴圈結束之後,j到i之間就沒有重複元素了 21 res = max(res, i - j + 1); 22 } 23 cout << res << endl; 24 return 0; 25 }