雙指標,離散化和區間合併
阿新 • • 發佈:2022-03-13
雙指標
時間複雜度普遍為O(n)
for (int i = 0, j = 0; i < n; i ++ )
{
while (j < i && check(i, j)) j ++ ;
// 具體問題的邏輯
}
#include <iostream> #include <cstring> #include <algorithm> using namespace std; const int N = 30; int a[N]; string s; int main() { cin >> s; int res = 0; for (int i = 0, j = 0; i < s.size(); i ++ ) { a[s[i] - 'a'] ++; while (j < i && a[s[i] - 'a'] > 1) { a[s[j] - 'a'] --; j ++; } res = max(res, i - j + 1); } cout << res << endl; return 0; }
常見問題分類:
(1) 對於一個序列,用兩個指標維護一段區間
(2) 對於兩個序列,維護某種次序,比如歸併排序中合併兩個有序序列的操作
離散化
對於大範圍,但是資料少的題,如果直接開相應陣列大小的話,時空可能會爆掉,所以可以將無限的空間,對映成有限的空間,一一對應。
思路是:
1.先排序
2.再刪除重複元素
3.最後就是索引元素離散化後對應的值。
vector<int> alls; // 儲存所有待離散化的值 sort(alls.begin(), alls.end()); // 將所有值排序 alls.erase(unique(alls.begin(), alls.end()), alls.end()); // 去掉重複元素 // 二分求出x對應的離散化的值 int find(int x) // 找到第一個大於等於x的位置 { int l = 0, r = alls.size() - 1; while (l < r) { int mid = l + r >> 1; if (alls[mid] >= x) r = mid; else l = mid + 1; } return r + 1; // 對映到1, 2, ...n }
區間合併
1.先對區間頭進行排序
2.然後持續更新尾部
// 將所有存在交集的區間合併 void merge(vector<PII> &segs) { vector<PII> res; sort(segs.begin(), segs.end()); int st = -2e9, ed = -2e9; for (auto seg : segs) if (ed < seg.first)//如果沒有交集 { if (st != -2e9) res.push_back({st, ed});//加入第一段區間 st = seg.first, ed = seg.second;//更新頭尾值 } else ed = max(ed, seg.second);//更新最大的尾值 if (st != -2e9) res.push_back({st, ed}); segs = res; }