1. 核心思想
通過某種線性關係將原先o(n2)的樸素演算法優化為o(n)的快速演算法
2. 一般應用思路
(1)先寫乙個暴力的樸素o(n2)的演算法
(2)找到兩個指標之間的單調關係
(3)如果有單調關係,可以將列舉從o(n2)優化到o(n)
3. 模板
for(int i = 0, j = 0; i < n; i++)例題1:單詞分割常見問題的分類:
(1)對於乙個序列,用兩個指標維護一段區間,如:快速排序中用兩個指標調整區間
(2) 對於兩個序列,維護某種次序,比如歸併排序中合併兩個有序序列的操作
把乙個句子中用空格隔開的單詞每個一行輸出
#include
#include
using
namespace std;
intmain()
cout << endl;
i = j;
}return0;
}
例2:最長連續不重複子序列
給定乙個長度為n的整數序列,請找出最長的不包含重複數字的連續區間,輸出它的長度。
輸入格式
第一行包含整數n。
第二行包含n個整數(均在0~100000範圍內),表示整數序列。
輸出格式
共一行,包含乙個整數,表示最長的不包含重複數字的連續子串行的長度。
資料範圍
1≤n≤100000
輸入樣例:
51 2 2 3 5
輸出樣例:
3
一般樸素做法:
用乙個兩層迴圈
for(
int i =
0; i < n; i++
)for
(int j = i; j < n; j++
)i在前,j在後維護的一段區間判重
這樣j每次都要退回,時間複雜度為o
(n^2
)
雙指標做法:
讓j在前, i在後維護一段區間
相當於乙個佇列,外層迴圈控制隊尾,內層迴圈控制隊頭
#include
using
namespace std;
const
int n =
100010
;int n;
int a[n]
, s[n]
;int
main()
res =
max(res, i - j +1)
;//計算最大序列長度
} cout << res << endl;
return0;
}
例3:日誌統計
小明維護著乙個程式設計師論壇。現在他收集了乙份」點讚」日誌,日誌共有 n 行。
其中每一行的格式是:
ts id表示在 ts 時刻編號 id 的帖子收到乙個」贊」。
現在小明想統計有哪些帖子曾經是」熱帖」。
如果乙個帖子曾在任意乙個長度為 d 的時間段內收到不少於 k 個讚,小明就認為這個帖子曾是」熱帖」。
具體來說,如果存在某個時刻 t 滿足該帖在 [t,t+d) 這段時間內(注意是左閉右開區間)收到不少於 k 個讚,該帖就曾是」熱帖」。
給定日誌,請你幫助小明統計出所有曾是」熱帖」的帖子編號。
輸入格式
第一行包含三個整數 n,d,k。
以下 n 行每行一條日誌,包含兩個整數 ts 和 id。
輸出格式
按從小到大的順序輸出熱帖 id。
每個 id 佔一行。
資料範圍
1≤k≤n≤105,
0≤ts,id≤105,
1≤d≤10000
輸入樣例:
7 10 2
0 10 10
10 10
10 1
9 1100 3
100 3
輸出樣例:13
解題思路:
利用pair儲存每條記錄,排序後用雙指標模擬佇列,每次入隊乙個記錄,並判斷當前佇列長度,如果佇列長度大於限制區間長度,就從隊頭出隊乙個元素。入隊出隊的同時記錄當前佇列中元素出現的次數,如果大於k就輸出
#include
#include
#include
#include
using
namespace std;
const
int n =
100010
;typedef pair<
int,
int> pii;
int n, d, k;
int cnt[n]
;pii logs[n]
;bool st[n]
;int
main()
if(cnt[id]
>= k) st[id]
=true;}
for(
int i =
0; i < n; i++)if
(st[i]
) cout << i << endl;
return0;
}
例4:完全二叉樹的權值
給定一棵包含 n 個節點的完全二叉樹,樹上每個節點都有乙個權值,按從上到下、從左到右的順序依次是 a1,a2,⋅⋅⋅an,如下圖所示:
現在小明要把相同深度的節點的權值加在一起,他想知道哪個深度的節點權值之和最大?
如果有多個深度的權值和同為最大,請你輸出其中最小的深度。
注:根的深度是 1。
輸入格式
第一行包含乙個整數 n。
第二行包含 n 個整數 a1,a2,⋅⋅⋅an。
輸出格式
輸出乙個整數代表答案。
資料範圍
1≤n≤105,
−105≤ai≤105
輸入樣例:
71 6 5 4 3 2 1
輸出樣例:
2解題思路:
題目要求求出和值最大的層數。按照完全二叉樹的標號順序,可以找到每一層起始元素與元素個數,所以只要利用雙指標演算法,乙個指標遍歷起始元素,另乙個指標遍歷每一層各個元素累加,就可以求出每層的和值,維護最大值即可。
#include
#include
using
namespace std;
const
int n =
100010
;typedef
long
long ll;
int a[n]
;int n;
intmain()
}
cout << depth << endl;
return0;
}
演算法基礎課 雙指標演算法
首先對於雙指標演算法,必須明確,對於此問題來說,只能是乙個優化問題,核心思想是把乙個o n2 的時間複雜度問題給優化到o n 來解決。通用模板 按照樸素演算法 for int i 0 i for int j 0 j 按照某種性質進行優化 for int i 0,j 0 i while jcheck ...
雙指標演算法
雙指標演算法模板 for int i 0,j 0 i n i 常見問題分類 1 對於乙個序列,用兩個指標維護一段區間 2 對於兩個序列,維護某種次序,比如歸併排序中合併兩個有序序列的操作 例題1 最長連續不重複子序列 給定乙個長度為n的整數序列,請找出最長的不包含重複數字的連續區間,輸出它的長度。輸...
雙指標演算法
title 雙指標演算法 date 2019 05 26 23 45 09 tags 雙指標演算法 雙指標演算法 主要是兩大類 核心思想 將乙個 o n 2 o n 2 o n2 的演算法 優化成 o n o n o n 的for int i 0 i for int j 0 j for i 0,j ...