#P4241. 第2题-最长子数组的长度
-
ID: 3317
Tried: 12
Accepted: 6
Difficulty: 4
所属公司 :
中国电信
时间 :25年10月17日场
-
算法标签>枚举哈希
第2题-最长子数组的长度
解题思路
-
核心判定:对子数组而言,若“出现次数最多的次数”只由某一个元素达到,则该子数组存在“唯一众数”。
-
算法:双重枚举子数组的左右端点(固定左端点,向右扩展),在扩展过程中用哈希表维护:
freq[x]
:当前子数组内元素x
的出现次数;maxFreq
:当前子数组内的最高出现次数;cntMax
:达到maxFreq
的元素个数。
-
增量更新:每次把右端点元素
x
加入:- 设旧次数为
f
,新次数为f+1
; - 若
f+1 > maxFreq
:更新maxFreq = f+1
,并置cntMax = 1
(只有x
达到新最高); - 若
f+1 == maxFreq
:cntMax += 1
; - 否则不变。
- 设旧次数为
-
判优:当且仅当
cntMax == 1
时,当前子数组存在唯一众数,更新答案长度。 -
正确性要点:上述更新能正确维护“最高频次数及其达成者个数”。当某个元素从与最高频持平再+1时,它会独占更高的
maxFreq
,我们将cntMax
重置为 1;当另一个元素追平时,cntMax
相应递增。由此可在扩展过程中随时判定是否存在唯一众数。
复杂度分析
- 外层枚举左端点
n
次,内层右扩最多n
次,每步为 O(1) 更新; - 时间复杂度:O(n²)(总和 n ≤ 2000,完全可行)。
- 空间复杂度:O(n)(哈希表在最坏情况下存放当前子数组的不同元素)。
代码实现
Python
# -*- coding: utf-8 -*-
import sys
from collections import defaultdict
# 功能函数:返回数组中存在唯一众数的最长子数组长度
def longest_unique_mode(arr):
n = len(arr)
ans = 0
for l in range(n):
freq = defaultdict(int) # 频次表
maxFreq = 0 # 当前最高频次
cntMax = 0 # 达到最高频次的元素个数
for r in range(l, n):
x = arr[r]
f = freq[x]
f += 1
freq[x] = f
if f > maxFreq:
maxFreq = f
cntMax = 1
elif f == maxFreq:
cntMax += 1
# 若唯一众数存在(仅一个元素达到最高频次),尝试更新答案
if cntMax == 1:
ans = max(ans, r - l + 1)
return ans
def main():
data = list(map(int, sys.stdin.buffer.read().split()))
it = iter(data)
T = next(it)
out_lines = []
for _ in range(T):
n = next(it)
arr = [next(it) for _ in range(n)]
out_lines.append(str(longest_unique_mode(arr)))
print("\n".join(out_lines))
if __name__ == "__main__":
main()
Java
// ACM 风格,类名为 Main
// 思路:双层枚举 + 哈希表维护 maxFreq 与 cntMax 的增量更新
import java.io.*;
import java.util.*;
public class Main {
// 功能函数:返回存在唯一众数的最长子数组长度
static int longestUniqueMode(int[] a) {
int n = a.length;
int ans = 0;
for (int l = 0; l < n; l++) {
HashMap<Integer, Integer> freq = new HashMap<>();
int maxFreq = 0; // 当前最高频次
int cntMax = 0; // 达到最高频次的元素个数
for (int r = l; r < n; r++) {
int x = a[r];
int f = freq.getOrDefault(x, 0) + 1;
freq.put(x, f);
if (f > maxFreq) {
maxFreq = f;
cntMax = 1;
} else if (f == maxFreq) {
cntMax++;
}
// 唯一众数存在时更新答案
if (cntMax == 1) {
ans = Math.max(ans, r - l + 1);
}
}
}
return ans;
}
public static void main(String[] args) throws Exception {
// 数据规模较小,使用 BufferedReader + StringTokenizer 足够
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String s;
s = br.readLine();
int T = Integer.parseInt(s.trim());
StringBuilder sb = new StringBuilder();
while (T-- > 0) {
int n = Integer.parseInt(br.readLine().trim());
StringTokenizer st = new StringTokenizer(br.readLine());
int[] a = new int[n];
for (int i = 0; i < n; i++) {
a[i] = Integer.parseInt(st.nextToken());
}
sb.append(longestUniqueMode(a)).append('\n');
}
System.out.print(sb.toString());
}
}
C++
// 思路:固定左端点右扩,哈希表维护 freq / maxFreq / cntMax 的增量变化
#include <bits/stdc++.h>
using namespace std;
// 功能函数:返回存在唯一众数的最长子数组长度
int longest_unique_mode(const vector<int>& a) {
int n = (int)a.size();
int ans = 0;
for (int l = 0; l < n; ++l) {
unordered_map<int, int> freq; // 频次表
int maxFreq = 0; // 当前最高频次
int cntMax = 0; // 达到最高频次的元素个数
for (int r = l; r < n; ++r) {
int x = a[r];
int f = ++freq[x];
if (f > maxFreq) {
maxFreq = f;
cntMax = 1;
} else if (f == maxFreq) {
cntMax++;
}
// 若唯一众数存在,更新答案
if (cntMax == 1) {
ans = max(ans, r - l + 1);
}
}
}
return ans;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int T;
if (!(cin >> T)) return 0;
while (T--) {
int n;
cin >> n;
vector<int> a(n);
for (int i = 0; i < n; ++i) cin >> a[i];
cout << longest_unique_mode(a) << "\n";
}
return 0;
}
题目内容
给定一个长度为n的整数序列a1,a2,...,an。我们称一个非空连续子数组al,al+1,...,ar,存在“唯一众数”,当且仅当在该子数组中,出现次数最多的数恰好只有一个(即最高频次仅由某一个数独占)。
请你求出存在唯一众数的最长子数组的长度。若不存在这样的子数组,则输出0。
名词解释:
子数组:指原序列中一段连续的元素al,al+1,...,ar(1≤l≤r≤n)。
唯一众数:在一个集合或序列中,出现次数最多的元素。若这一“最多次数”由多个不同元素同时达到,则不存在“唯一众数"。
输入描述
每个测试文件均包含多组测试数据。第一行输入一个整数 T(1≤T≦103)代表数据组数,每组测试数据描述如下:
第一行输入一个整数n(1≦n≦2×103);
第二行输入n个整数a1,a2,...,an(∣ai∣≦109)
保证所有测试中n的总和不超过2×103。
输出描述
对于每组测试数据,输出一行一个整数,表示存在唯一众数的最长子数组长度;若不存在,输出0
样例1
输入
3
5
1 2 2 3 3
3
7 7 7
4
1 1 2 2
输出
4
3
3
说明
样例一:整个数组的最高频次由2和3同时达到,不是唯众数;但子数组[1,2,2,3]中2的频次为2且独占最高频,长度为4,为最优。
样例二:[7,7,7]的众数为7且唯一,答案为3。
样例三:[1,1,2]或[1,2,2]的众数分别为1或2,且均唯一,最长长度为3。