AcWing 799. 最长连续不重复子序列——算法基础课题解

AcWing 799. 最长连续不重复子序列

题目描述

给定一个长度为 n 的整数序列,请找出最长的不包含重复的数的连续区间,输出它的长度。

输入格式

第一行包含整数 n。

第二行包含 n 个整数(均在 0∼10^5 范围内),表示整数序列。

输出格式

共一行,包含一个整数,表示最长的不包含重复的数的连续区间的长度。

数据范围

1≤n≤10^5

输入样例

cpp 复制代码
5
1 2 2 3 5

输出样例

cpp 复制代码
3

C++

cpp 复制代码
#include <iostream>

using namespace std;

const int N = 1e5 + 10;

int arr[N], count[N];


int main() {
    int n, res = 0;
    scanf("%d", &n);
    for (int i = 0; i < n; i++) scanf("%d", &arr[i]);
    for (int l = 0, r = 0; r < n; r++) {
        count[arr[r]]++;
        while (l < r && count[arr[r]] > 1) count[arr[l++]]--;
        res = max(res, r - l + 1);
    }
    printf("%d", res);
    return 0;
}
cpp 复制代码
#include <iostream>

using namespace std;

const int N = 100010;

int n;
int q[N], s[N];

int main() {
    scanf("%d", &n);
    for (int i = 0; i < n; i++) scanf("%d", &q[i]);

    int res = 0;
    for (int i = 0, j = 0; i < n; i++) {
        s[q[i]]++;
        while (j < i && s[q[i]] > 1) s[q[j++]]--;
        res = max(res, i - j + 1);
    }

    cout << res << endl;

    return 0;
}
  1. 右指针 i
    • 右指针 i 用于遍历数组 q 中的每一个元素。
    • 它从数组的第一个元素开始,逐步向右移动,直到达到数组的最后一个元素。
    • 在每次迭代中,i 指向当前正在考虑的数组元素。
  2. 左指针 j
    • 左指针 j 表示当前考虑的窗口的左边界。
    • 它的起始位置也是数组的起始位置,但它会根据需要向右移动,以调整窗口的大小,确保窗口内的所有元素都是唯一的(无重复)。
    • 如果右指针 i 指向的元素由于重复而需要调整窗口大小,那么 j 将向右移动,直到该重复元素的计数恢复为 1 或更少。

Go

go 复制代码
package main

import (
	"bufio"
	"fmt"
	"os"
)

func max(a, b int) int {
	if a > b {
		return a
	}
	return b
}

func main() {
	var n, res int
	reader := bufio.NewReader(os.Stdin)
	fmt.Fscan(reader, &n)
	arr := make([]int, n)
	count := make(map[int]int)
	for i := 0; i < n; i++ {
		fmt.Fscan(reader, &arr[i])
	}
	for l, r := 0, 0; r < n; r++ {
		count[arr[r]]++
		for l < r && count[arr[r]] > 1 {
			count[arr[l]]--
			l++
		}
		res = max(res, r-l+1)
	}

	writer := bufio.NewWriter(os.Stdout)
	defer writer.Flush()
	fmt.Fprint(writer, res)
}
go 复制代码
package main

import (
	"bufio"
	"fmt"
	"os"
)

const N int = 1e5 + 10

func max(a, b int) int {
	if a > b {
		return a
	}
	return b
}

func main() {
	var n, res int
	reader := bufio.NewReader(os.Stdin)
	fmt.Fscan(reader, &n)
	arr := make([]int, n)
	count := make([]int, N)
	for i := 0; i < n; i++ {
		fmt.Fscan(reader, &arr[i])
	}
	for l, r := 0, 0; r < n; r++ {
		count[arr[r]]++
		for l < r && count[arr[r]] > 1 {
			count[arr[l]]--
			l++
		}
		res = max(res, r-l+1)
	}

	writer := bufio.NewWriter(os.Stdout)
	defer writer.Flush()
	fmt.Fprint(writer, res)
}

模板

cpp 复制代码
for (int i = 0, j = 0; i < n; i ++ )
{
    while (j < i && check(i, j)) j ++ ;

    // 具体问题的逻辑
}
常见问题分类:
    (1) 对于一个序列,用两个指针维护一段区间
    (2) 对于两个序列,维护某种次序,比如归并排序中合并两个有序序列的操作
相关推荐
董董灿是个攻城狮5 小时前
AI视觉连载8:传统 CV 之边缘检测
算法
哈里谢顿5 小时前
1000台裸金属并发创建中的重难点问题分析
面试
哈里谢顿5 小时前
20260303面试总结(全栈)
面试
over69710 小时前
从 LLM 到全栈 Agent:MCP 协议 × RAG 技术如何重构 AI 的“做事能力”
面试·llm·mcp
SuperEugene11 小时前
Vue状态管理扫盲篇:如何设计一个合理的全局状态树 | 用户、权限、字典、布局配置
前端·vue.js·面试
AI软著研究员12 小时前
程序员必看:软著不是“面子工程”,是代码的“法律保险”
算法
FunnySaltyFish12 小时前
什么?Compose 把 GapBuffer 换成了 LinkBuffer?
算法·kotlin·android jetpack
颜酱13 小时前
理解二叉树最近公共祖先(LCA):从基础到变种解析
javascript·后端·算法
Sailing13 小时前
🚀 别再乱写 16px 了!CSS 单位体系已经进入“计算时代”,真正的响应式布局
前端·css·面试
SuperEugene16 小时前
Vue状态管理扫盲篇:Vuex 到 Pinia | 为什么大家都在迁移?核心用法对比
前端·vue.js·面试