双指针模板
其实也没啥模板 具体情况还要具体分析哦
for(int = 0 , j = 0; i < n; i++)
{
while(j < i && check(i,j)) j++;
//每道题的具体逻辑
}
经典解法 最长连续不重复子序列
思路 :
个例子,加入输入一条整数序列,12235,定义i,j两指针,当i指向第一个位置的时候,j也指向第一个位置,如下图所示。
-
此时,i移动到下一个位置2,此时j和i之间没有重复数字,所以i继续移动到第三个位置2。
-
此时出现重复数字所以,j开始移动到第二个位置2,此时j位置的值跟i位置的值还是重复,所以j继续移动到第三个位置,i,j重合(判断a[i] ! = a[j])。
-
此时,i继续往第四个位置移动,重复上述操作,一直移动到第五个位置没有重复。
-
c++代码
#include <iostream>
using namespace std;
const int N = 100010;
int n;
int a[N], s[N];//a[N]整数序列,s[N]表示当前j到i区间每一个数出现的次数。
int main()
{
cin >> n;
for (int i = 0; i < n; i ++) cin >> a[i];//读入n个数
int res = 0;//存储最大不重复字符串长度
for (int i = 0, j = 0; i < n; i ++)
{
s[a[i]] ++;//标记第a[i]个位置的数,表示加入了这个数
while(s[a[i]] > 1)//判断a[i]位置的数是否出现重复,如果<=1说明没有重复。
{
//如果出现重复
s[a[j]] --;//把j拿出去
j ++;//j往后移
}
res = max(res, i - j + 1);//存最大的数
}
cout << res << endl;
return 0;
}
java代码
import java.io.*;
public class Main {
static final int N = 100010;
static int[] a = new int[N];
static int[] s = new int[N];
public static void main(String[] args) throws IOException {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
String str1 = in.readLine();
String[] str2 = in.readLine().split(" ");
int n = Integer.parseInt(str1);
for(int i = 0; i < n; i++) {
a[i] = Integer.parseInt(str2[i]);
}
int res = 0;
for (int i = 0, j = 0; i < n; i++) {
s[a[i]]++;
while(s[a[i]] > 1) {
s[a[j]]--;
j++;
}
res = Math.max(res, i-j+1);
}
System.out.println(res);
}
}
java hashmap改进使用于字符等等
import java.lang.*;
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[] a = new int[100010];
for(int i =0; i<n; i++) a[i] = sc.nextInt();
Map<Integer,Integer> map = new HashMap<>(); //当前值 和 出现的次数
int max = 0; //最大长度
for(int i = 0 ,j = 0; i<n ;i++){
map.put(a[i],map.getOrDefault(a[i],0)+1); //i是要一直往后移动的那个
while(map.get(a[i])>1) //窗口收缩的条件 当i移动到某一值,窗口中已经有了该值的时候
{
map.put(a[j],map.get(a[j])-1); //前面的值挨个出窗口 知道当等于a[i]的值出去就会停止循环 i(窗口)继续向后扩展
j++;
}
max = Math.max(max,i-j+1); //求最大的长度
}
System.out.println(max);
//输出结果
}
}
题目二 : 数组元素的目标和
数组元素的目标和
给定两个升序排序的有序数组 A 和 B,以及一个目标值 x。
数组下标从 0 开始。
请你求出满足 A[i]+B[j]=x 的数对 (i,j)。
数据保证有唯一解。
输入格式
第一行包含三个整数 n,m,x,分别表示 A 的长度,B 的长度以及目标值 x。第二行包含 n 个整数,表示数组 A。
第三行包含 m 个整数,表示数组 B。
输出格式
共一行,包含两个整数 i 和 j。数据范围
数组长度不超过 105。
同一数组内元素各不相同。
1≤数组元素≤109
输入样例:
4 5 6
1 2 4 7
3 4 6 8 9
输出样例:
1 1题解
import java.util.*; public class Main{ public static void main(String[] args){ //读入数据 Scanner sc = new Scanner(System.in); int n = sc.nextInt(); int m = sc.nextInt(); int x = sc.nextInt(); int [] A = new int[100010]; int [] B = new int[100010]; for(int i =0; i<n; i++) A[i] = sc.nextInt(); for(int i =0; i<m; i++) B[i] = sc.nextInt(); //解法一 : for+ 二分 算法开始 O(nlogn) 4625 ms // for(int i = 0; i<n; i++){ // int target = x - A[i]; // int l = 0; // int r = m-1; // while(l<r){ // int mid = l + r >> 1; // if(B[mid]==target) { // System.out.println(i+" "+mid); // return; // }else if(B[mid]<target) l = mid + 1; // else r = mid; // } // } //解法二 : 双指针 O(n+m) 4645 ms for(int i = 0,j = m-1; i<n; i++){ while(j>=0 && A[i]+B[j]>x ) j--; if(A[i]+B[j] == x) { System.out.println(i+" "+j);//j从后往前移 移到和小于等于的时候停止 判断如果等于返回结果 否则i右移 return; } } } }
题目三 : 判断子序列
给定一个长度为 n 的整数序列 a1,a2,…,an 以及一个长度为 m 的整数序列 b1,b2,…,bm。
请你判断 a 序列是否为 b 序列的子序列。
子序列指序列的一部分项按原有次序排列而得的序列,例如序列 {a1,a3,a5} 是序列 {a1,a2,a3,a4,a5} 的一个子序列。
输入格式
第一行包含两个整数 n,m。
第二行包含 n 个整数,表示 a1,a2,…,an。
第三行包含 m 个整数,表示 b1,b2,…,bm。
输出格式
如果 aa 序列是 bb 序列的子序列,输出一行
Yes
。否则,输出
No
。数据范围
1≤n≤m≤105,
−109≤ai,bi≤109输入样例:
3 5 1 3 5 1 2 3 4 5
输出样例:
Yes
//解法 双指针 O(n) int i = 0,j = 0; while(j<m &&i<n){ if( B[j] == A[i])i++; j++; } if(i == n) System.out.println("Yes"); else System.out.println("No");