双指针算法

135 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

一、双指针法的定义:所谓双指针法,就是利用两个指针(不一定是真指针,能储存相应元素的位置就行)分别标识两个位置,然后通过指针所指元素的性质对数组(或者链表结点)进行修改,同时移动指针完成目标的方法。
二、双指针法的四种使用方法:

  1. 用快指针指向符合条件的数据填充慢指针指向的位置;
  2. 两个指针指向的元素相互比较,选出符合条件 的元素填入指定容器;
  3. 解决一遍遍历解决不了但两遍或多次遍历能解决的问题;
  4. 通过快慢指针的移动以及两者的相遇选出的特定条件。

三、暴力算法和双指针算法有什么区别:

  • 暴力算法每次在第二层遍历的时候,是会重新开始(第二层循环的 j 会回溯的初始位置),然后再遍历下去。
  • 双指针算法:由于某种单调性,每次再第二层遍历的时候,不需要回溯到初始位置(单调性),而是在满足要求的位置继续走下去或者更新掉。

【C++双指针法】5道题带你认识双指针法

快排和归并排序都是双指针算法
在这里插入图片描述
双指针算法会将上述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范围内),表示整数序列。

输出格式

共一行,包含一个整数,表示最长的不包含重复数字的连续子序列的长度。

数据范围

1n1000001≤n ≤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;
}

由于还没讲数据结构,所以先用数组存,如果数据大的话,可以用哈希表判重,可以判断字母或者数字,数字可以任意大。