题目描述
给定一个整数数组 A
和整数 K
,统计数组中满足「K-优雅数组」条件的子数组数量。
K-优雅数组定义:数组中出现次数最多的元素出现次数 ≥ K。
子数组:数组中一个或多个连续元素组成的数组。
示例说明
- 数组
[2, 3, 1, 2, 3, 1, 2, 3, 1]
是 3-优雅数组(元素1
出现 3 次)。 - 数组
[2, 3, 1, 2, 3, 1]
不是 3-优雅数组(最高频率为 2 次)。
子数组示例
例如,数组 [1, 2, 3, 4]
包含 10 个子数组,分别是:
[1]
, [1, 2]
, [1, 2, 3]
, [1, 2, 3, 4]
, [2]
, [2, 3]
, [2, 3, 4]
, [3]
, [3, 4]
, [4]
输入输出格式
输入描述
- 第一行:两个空格分隔的整数
n
(数组长度)和K
(优雅阈值)。 - 第二行:
n
个空格分隔的整数表示数组元素。
输出描述
- 一个整数,表示满足条件的子数组数量。
输入输出示例
输入示例
6 3
1 2 1 2 1 2
输出示例
3
示例解释:
满足条件的子数组为:
[1,2,1,2,1]
, [2,1,2,1,2]
, [1,2,1,2,1,2]
。
解题思路
暴力枚举优化
- 遍历所有子数组:通过双重循环枚举子数组的起止点。
- 频率统计:使用哈希表记录当前子数组中元素的出现次数。
- 实时更新最大值:每次添加新元素后更新最大频率,若满足条件则计数。
时间复杂度:O(n²),适用于 n ≤ 1e3。
空间复杂度:O(n),哈希表存储频率。
代码实现
Python
n, k = map(int, input().split())
a = list(map(int, input().split()))
count = 0
for left in range(n):
freq = {}
max_freq = 0
for right in range(left, n):
num = a[right]
freq[num] = freq.get(num, 0) + 1
if freq[num] > max_freq:
max_freq = freq[num]
if max_freq >= k:
count += 1
print(count)
Java
题解一
import java.util.HashMap;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int k = sc.nextInt();
int[] a = new int[n];
for (int i = 0; i < n; i++) {
a[i] = sc.nextInt();
}
int count = 0;
for (int left = 0; left < n; left++) {
HashMap<Integer, Integer> freq = new HashMap<>();
int maxFreq = 0;
for (int right = left; right < n; right++) {
int num = a[right];
freq.put(num, freq.getOrDefault(num, 0) + 1);
if (freq.get(num) > maxFreq) {
maxFreq = freq.get(num);
}
if (maxFreq >= k) {
count++;
}
}
}
System.out.println(count);
}
}
题解二
import java.util.*;
public class K优雅子数组 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int N = sc.nextInt();
int K = sc.nextInt();
int[] arr = new int[N];
for (int i = 0; i < N; i++) {
arr[i] = sc.nextInt();
}
List<List<Integer>> lists = new ArrayList<>();
List<Integer> list = new ArrayList<>();
for (int i = 0; i < N; i++) {
for (int j = i; j < N; j++) {
list.add(arr[j]);
lists.add(List.copyOf(list));
}
list = new ArrayList<>();
}
int res = 0;
for (List<Integer> item : lists) {
Map<Integer, Integer> map = new HashMap<>();
if (item.size() >= K) {
item.forEach(element -> map.put(element, map.getOrDefault(element, 0) + 1));
}
for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
if (entry.getValue() >= K) {
res++;
break;
}
}
}
System.out.println(res);
}
}
C++
#include <iostream>
#include <vector>
#include <unordered_map>
using namespace std;
int main() {
int n, k;
cin >> n >> k;
vector<int> a(n);
for (int i = 0; i < n; i++) {
cin >> a[i];
}
int count = 0;
for (int left = 0; left < n; left++) {
unordered_map<int, int> freq;
int max_freq = 0;
for (int right = left; right < n; right++) {
int num = a[right];
freq[num]++;
if (freq[num] > max_freq) {
max_freq = freq[num];
}
if (max_freq >= k) {
count++;
}
}
}
cout << count << endl;
return 0;
}
JavaScript
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
let input = [];
rl.on('line', (line) => {
input.push(line);
}).on('close', () => {
const [n, k] = input[0].split(' ').map(Number);
const a = input[1].split(' ').map(Number);
let count = 0;
for (let left = 0; left < n; left++) {
const freq = new Map();
let maxFreq = 0;
for (let right = left; right < n; right++) {
const num = a[right];
freq.set(num, (freq.get(num) || 0) + 1);
if (freq.get(num) > maxFreq) {
maxFreq = freq.get(num);
}
if (maxFreq >= k) {
count++;
}
}
}
console.log(count);
});
复杂度分析
- 时间复杂度:O(n²),双重循环遍历所有子数组。
- 空间复杂度:O(n),哈希表存储元素频率。
总结
- 关键点:通过哈希表动态维护子数组元素频率,避免重复计算。
- 优化方向:对于更大数据量,可探索滑动窗口或频率剪枝策略。
- 适用场景:适用于面试场景下对基础暴力解法的考察。