基礎演算法 雙指標演算法

2021-10-08 03:50:17 字數 3823 閱讀 6388

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)對於乙個序列,用兩個指標維護一段區間,如:快速排序中用兩個指標調整區間

(2) 對於兩個序列,維護某種次序,比如歸併排序中合併兩個有序序列的操作

例題1:單詞分割

把乙個句子中用空格隔開的單詞每個一行輸出

#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 ...