本文已参与「新人创作礼」活动,一起开启掘金创作之路。
一、双指针法的定义:所谓双指针法,就是利用两个指针(不一定是真指针,能储存相应元素的位置就行)分别标识两个位置,然后通过指针所指元素的性质对数组(或者链表结点)进行修改,同时移动指针完成目标的方法。
二、双指针法的四种使用方法:
- 用快指针指向符合条件的数据填充慢指针指向的位置;
- 两个指针指向的元素相互比较,选出符合条件 的元素填入指定容器;
- 解决一遍遍历解决不了但两遍或多次遍历能解决的问题;
- 通过快慢指针的移动以及两者的相遇选出的特定条件。
三、暴力算法和双指针算法有什么区别:
- 暴力算法每次在第二层遍历的时候,是会重新开始(第二层循环的 j 会回溯的初始位置),然后再遍历下去。
- 双指针算法:由于某种单调性,每次再第二层遍历的时候,不需要回溯到初始位置(单调性),而是在满足要求的位置继续走下去或者更新掉。
快排和归并排序都是双指针算法
双指针算法会将上述O(n²)的朴素算法变为O(n)
例子:
输入一个字符串,单词间用空格分开,输出单词,每个单词占一行
#include <iostream>
#include <string.h>
using namespace std;
int main()
{
char str[1000];
gets(str);
int n = strlen(str);
for(int i = 0; i < n; i++)
{
int j = i;
while(j < n && str[j] != ' ') j++;
for(int k = i; k < j; k++)cout << str[k];
cout << endl;
i = j;
}
return 0;
}
799.最长连续不重复子序列
给定一个长度为n的整数序列,请找出最长的不包含重复数字的连续子序列,输出它的长度。
输入格式
第一行包含整数n。
第二行包含n个整数(均在0~100000范围内),表示整数序列。
输出格式
共一行,包含一个整数,表示最长的不包含重复数字的连续子序列的长度。
数据范围
输入样例:
5
1 2235 输出样例:
3
先写一个暴力做法,看一看ij之间有没有单调关系,有的话就可以用这种关系把枚举的复杂度从n²变成n
数据比较小,只有十万,check的编写可以开一个数组,动态的记录每一个数字出现多少次
#include <iostream>
using namespace std;
const int N = 100010;
int n;
int a[N], s[N];//a是所有的数,s是当前j到i区间内每一个数出现的次数
int main()
{
cin >> n;
for(int i = 0; i < n; i++) cin >> a[i];
int res = 0;
for(int i = 0, j = 0; i < n; i++)
{
s[a[i]]++;
while(s[a[i]] > 1)//因为j如果在i右边,则没有数,也就不可能有重复,就会退出循环让i往右移动
{
s[a[j]]--;
j++;
}
res = max(res, i - j + 1);
}
cout << res << endl;
return 0;
}
由于还没讲数据结构,所以先用数组存,如果数据大的话,可以用哈希表判重,可以判断字母或者数字,数字可以任意大。