尺取法
一.概念
设:现在有一个有序的区间,要两个变量 i 和 j 扫描区间。
对于上方应用,一般做法是用 i 和 j 分别扫描区间,有二重循环,复杂度为 O(n^2)。以反向搜索(即 i 和 j 的方向相反,后文有解释)为例,代码如下:
for(int i=0;i<n;i++)//i从头到尾 for(int j=n-1;j>=0;j--)//j从尾到头 { ... }
下面用尺取法优化:
实际上,尺取法就是把二重循环变为一重,在循环中同时处理 i 和 j。复杂度也变味 O(n),以上方为例:
//while实现
int i=0,j=n-1; while(i<j) { ... i++; j--; } //for实现 for(int i=0,j=n-1;i<j;i++,j--) { ... }
上图:
重点:扫描方向
1.反向扫描(左右指针)
i,j方向相反,i从头到尾,j从尾到头,在中间相会
2.同向扫描(快慢指针)
i,j方向相同,都从头到尾,速度不同,如让j跑在i前面
二.反向扫描
例题:洛谷B2124
代码:
#include <iostream> using namespace std; int main() { string s; cin>>s; int i=0,j=s.size()-1; while(i<j) { if(s[i]!=s[j]) { cout << "no\n"; return 0; } i++; j--; } cout << "yes\n"; return 0; }
三.同向扫描