题解:学而思编程 最长平台(二)

【题目来源】

洛谷:最长平台(二)

【题目描述】

已知一个数列,这个数列中的一个平台就是连续的一串值相同的元素,并且这一串元素不能再延伸。例如,在 \(1,2,2,3,3,3,4,5,5\) 中的 \([1]\)\([2,2]\)\([3,3,3]\)\([4]\)\([5,5]\) 都是平台,最长平台的长度为 \(3\)

给定一个整数数列 \(a_1,a_2,…,a_n\)​,请找出最长平台,并输出最长平台的数量。

【输入】

第一行,包含一个正整数 \(n\),表示数列长度

第二行,包含 \(n\) 个正整数 \(a_1,a_2,…,a_n\)​​,表示数列,用空格隔开。

【输出】

一行包含两个整数:表示最长平台的长度与最长平台的数量。

【输入样例】

7
2 2 2 1 3 3 3

【输出样例】

3 2

【核心思想】

  1. 问题分析:给定长度为 \(n\) 的数列 \(a_1, a_2, \ldots, a_n\),平台定义为无法再向左右延伸的连续相同元素段。需要找出最长平台的长度以及该长度的平台数量。这是一个线性扫描 + 哈希统计问题,关键在于一次遍历识别所有平台,并用映射表记录各长度出现的频次。

  2. 算法选择

    • 线性扫描:遍历数组,维护当前连续相同元素的长度 cnt
    • 哈希映射:用 map 记录每种平台长度出现的次数
    • 极值提取:遍历映射表找出最大长度及其频次
  3. 关键步骤

    • 初始化:读取 \(n\) 和数组 \(a[1..n]\)
    • 扫描平台(遍历 \(i\)\(1\)\(n\)):
      • a[i] == a[i-1]cnt++(当前平台长度加 \(1\)
      • 否则:mp[cnt]++(记录前一个平台的长度),cnt = 1(重置计数,新平台从当前元素开始)
    • 处理末尾:循环结束后,mp[cnt]++(记录最后一个平台的长度)
    • 提取答案
      • 遍历 mp 中所有 (长度, 频次) 对:
        • 若当前长度 > maxn:更新 maxnmaxcnt
    • 输出 maxnmaxcnt
  4. 时间/空间复杂度

    • 时间复杂度:\(O(n + U)\)\(U\) 为不同平台长度的种类数(\(U \leq n\)),线性扫描 \(O(n)\),映射表遍历 \(O(U)\)
    • 空间复杂度:\(O(U)\),映射表存储各长度频次
  5. 线性扫描的核心思想

    • 平台识别:相邻元素相等则延长当前平台,不等则结束当前平台并开始新平台,保证每个平台只被计数一次
    • 边界处理:数组首元素作为第一个平台的起点,末尾平台在循环结束后单独处理,避免遗漏
    • 频次统计map 自动聚合相同长度的平台,无需预先知道长度范围
    • 极值提取:映射表按键有序,但本题只需找最大值,线性遍历即可
    • 适用于"连续段识别 + 段长度统计"类问题,线性扫描配合哈希映射可高效处理所有连续子段信息

【算法标签】

模拟

【代码详解】

#include <bits/stdc++.h>
using namespace std;
const int N = 200005;  // 定义最大数组长度
int n;  // 数组长度
int a[N];  // 数组a
map<int, int> mp;  // 记录长度和频次的映射表
int main()  // 主函数
{
    cin >> n;  // 输入数组长度
    for (int i=1; i<=n; i++)  // 读取数组元素
        cin >> a[i];  // 输入第i个元素
    int cnt = 1;  // 当前连续相同序列长度
    for (int i=1; i<=n; i++)  // 遍历数组
        if (a[i]==a[i-1])  // 如果当前元素等于前一个元素
        {
            cnt++;  // 连续长度加1
        }
        else  // 如果不相等
        {
            mp[cnt]++;  // 记录前一个连续序列的长度
            cnt = 1;  // 重置连续长度计数
        }
    if (a[n]==a[n-1]) mp[cnt]++;  // 处理最后一个连续序列
    int maxn = -1e9, maxcnt = 0;  // 最大长度和其出现次数
    for (auto it : mp)  // 遍历映射表
    {
        if (it.first>maxn)  // 如果当前长度更大
        {
            maxn = it.first;  // 更新最大长度
            maxcnt = it.second;  // 更新出现次数
        }
    }
    cout << maxn << " " << maxcnt << endl;  // 输出结果
    return 0;  // 程序正常结束
}

【运行结果】

7
2 2 2 1 3 3 3
3 2
posted @ 2026-07-04 14:25  团爸讲算法  阅读(7)  评论(0)    收藏  举报