双指针
双指针
系统的学了一下。
链上问题:
一般是用一个快指针 f
,一个慢指针 s
。
这里默认起始时 \(f\gets head,s\gets head\)
判环:
每次:\(f\gets f+2,s\gets s+1\)
若前进后 \(f=s\) 则有环。
相当于追及。
求环的起点:
先每次:\(f\gets f+2,s\gets s+1\)
在 \(f=s\) 后:
\(s\gets head\)
每次:\(f\gets f+1,s\gets s+1\)
当 \(f=s\) 时 \(f\) 即为起点。
证明:
第一次 \(f=s\) 时:
设相遇点距起点 \(x\)
显然第二次 \(f=s\) 时,\(s=f=\text{起点}\),\(new\_len_s=new\_len_f=\text{环长}-x\)。
画图感性理解一下
求中点:
每次:\(f\gets f+2,s\gets s+1\)
\(f=tail\) 时 \(s=mid\)
求终点前 \(k\) 个:
起始:\(f\gets head+k,s\gets head\)
每次:\(f\gets f+1,s\gets s+1\)
\(f=tail\) 时 \(s=tail-k\)
感觉也就求、判环有点用。
真·双指针
两个指针:\(l,r\)
指针表示当前状态,根据当前状态转移(一般直接贪心)
显然,用双指针的问题必须满足:
-
有 \(>\) 或 \(<\) 定义(值 \(v\) 可比)——可比性:
就是对于一种状态,可以 \(\operatorname{O}(1)\) 判断如何修改区间。
-
对于 \(l_1,r_1,l_2,r_2,l_3,r_3\) 当 \(v_1<v_2,v_2<v_3\) 时,\(v_1<v_3\)(\(>\) 同理,\(v_i\) 为 \(l_1,r_1\) 的值)——传递性
名字我瞎起的,以下就这么称呼。
类似二分答案满足的性质(因为二分也是双指针)
例子:
-
二分查找:
给定一个升序序列 \(a\),求第一个 \(\le x\) 的数。
状态 \(l,r\) 的值 \(v=a_{mid}\)
初始 \(l=1,r=n\)
可比性:对于 \(l,r\),有 \(v<x\) 时 \(l\gets mid+1\),否则 \(r\gets mid-1\)
传递性:对于 \(l_1,r_1,l_2,r_2,l_3,r_3\) 当 \(v_1<v_2,v_2<v_3\) 时 \(v_1<v_3\)
-
两数之和:
给定一个升序序列 \(a\) 和自然数 \(k\),求其中两个数 \(x,y\) 满足 \(x+y=k\)
状态 \(l,r\) 的值 \(v=a_l+a_r\)。
初始 \(l=1,r=n\)
可比性:对于 \(l,r\),有 \(v<x\) 时 \(l\gets l+1\),否则 \(r\gets r-1\)
传递性:对于 \(l_1,r_1,l_2,r_2,l_3,r_3\) 当 \(v_1<v_2,v_2<v_3\) 时 \(v_1<v_3\)
-
状态 \(l,r\) 的值 \(v=[l\text{ 到 }r\text{ 满足题意(均不相同)}]\)
初始 \(l=r=1\)
可比性:对于 \(l,r\),有 \(v=1\) 时 \(l\gets l+1\),否则 \(r\gets r+1\)
传递性:对于 \(l_1,r_1,l_2,r_2,l_3,r_3\) 当 \(v_1<v_2,v_2<v_3\) 时 \(v_1<v_3\) (\(0<1\))
本文来自博客园,作者:xrlong,转载请注明原文链接:https://www.cnblogs.com/xrlong/articles/17834885.html
版权声明:本作品采用 「署名-非商业性使用-相同方式共享 4.0 国际」许可协议(CC BY-NC-SA 4.0) 进行许可。