双指针模板 最长连续不重复子序列

双指针模板

其实也没啥模板 具体情况还要具体分析哦

for(int = 0 , j = 0; i < n; i++)
{
   while(j < i && check(i,j)) j++;
    
    //每道题的具体逻辑
    
}

经典解法 最长连续不重复子序列

思路 :

个例子,加入输入一条整数序列,12235,定义i,j两指针,当i指向第一个位置的时候,j也指向第一个位置,如下图所示。

img-

此时,i移动到下一个位置2,此时j和i之间没有重复数字,所以i继续移动到第三个位置2。

img-

此时出现重复数字所以,j开始移动到第二个位置2,此时j位置的值跟i位置的值还是重复,所以j继续移动到第三个位置,i,j重合(判断a[i] ! = a[j])。

img-

此时,i继续往第四个位置移动,重复上述操作,一直移动到第五个位置没有重复。

img-

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");
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值