
文章目录
【华为OD】找出通过车辆最多颜色
题目描述
在一个狭小的路口,每秒只能通过一辆车,假如车辆的颜色只有3种,找出N秒内经过的最多颜色的车辆数量,三种颜色编号为0, 1, 2。
输入
第一行输入的是通过的车辆颜色信息。比如[0,1,1,2] 代表4秒钟通过的车辆颜色分别是0, 1, 1, 2 第二行输入的是统计时间窗,整型,单位为秒。
输出
输出指定时间窗内经过的最多颜色的车辆数量
示例一
输入:
0 1 2 1
3
输出:
2
说明:
在[1,2,1] 这个3秒时间窗内,1这个颜色出现2次,数量最多
示例二
输入:
0 1 2 1
2
输出:
1
说明:
在2秒时间窗内,每个颜色最多出现1次
解题思路
这是一个典型的滑动窗口问题。我们需要在给定的时间窗口内,找出出现次数最多的颜色的数量。
核心思路:
- 使用滑动窗口遍历所有可能的时间窗口
- 对每个窗口内的颜色进行计数
- 找出每个窗口中出现次数最多的颜色
- 返回所有窗口中的最大值
解法一:暴力解法
思路
对每个可能的窗口位置,统计窗口内每种颜色的出现次数,找出最大值。
Java实现
java
import java.util.*;
public class Solution1 {
public static int findMaxColorCount(int[] cars, int windowSize) {
int n = cars.length;
int maxCount = 0;
// 遍历所有可能的窗口起始位置
for (int i = 0; i <= n - windowSize; i++) {
// 统计当前窗口内每种颜色的数量
int[] colorCount = new int[3]; // 0, 1, 2三种颜色
for (int j = i; j < i + windowSize; j++) {
colorCount[cars[j]]++;
}
// 找出当前窗口内最多的颜色数量
int currentMax = Math.max(colorCount[0], Math.max(colorCount[1], colorCount[2]));
maxCount = Math.max(maxCount, currentMax);
}
return maxCount;
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String[] input = scanner.nextLine().split(" ");
int[] cars = new int[input.length];
for (int i = 0; i < input.length; i++) {
cars[i] = Integer.parseInt(input[i]);
}
int windowSize = scanner.nextInt();
System.out.println(findMaxColorCount(cars, windowSize));
}
}
Python实现
python
def find_max_color_count(cars, window_size):
n = len(cars)
max_count = 0
# 遍历所有可能的窗口起始位置
for i in range(n - window_size + 1):
# 统计当前窗口内每种颜色的数量
color_count = [0, 0, 0] # 0, 1, 2三种颜色
for j in range(i, i + window_size):
color_count[cars[j]] += 1
# 找出当前窗口内最多的颜色数量
current_max = max(color_count)
max_count = max(max_count, current_max)
return max_count
# 输入处理
cars = list(map(int, input().split()))
window_size = int(input())
print(find_max_color_count(cars, window_size))
C++实现
cpp
#include <iostream>
#include <vector>
#include <algorithm>
#include <sstream>
using namespace std;
int findMaxColorCount(vector<int>& cars, int windowSize) {
int n = cars.size();
int maxCount = 0;
// 遍历所有可能的窗口起始位置
for (int i = 0; i <= n - windowSize; i++) {
// 统计当前窗口内每种颜色的数量
vector<int> colorCount(3, 0); // 0, 1, 2三种颜色
for (int j = i; j < i + windowSize; j++) {
colorCount[cars[j]]++;
}
// 找出当前窗口内最多的颜色数量
int currentMax = *max_element(colorCount.begin(), colorCount.end());
maxCount = max(maxCount, currentMax);
}
return maxCount;
}
int main() {
string line;
getline(cin, line);
istringstream iss(line);
vector<int> cars;
int num;
while (iss >> num) {
cars.push_back(num);
}
int windowSize;
cin >> windowSize;
cout << findMaxColorCount(cars, windowSize) << endl;
return 0;
}
解法二:滑动窗口优化
思路
使用滑动窗口技术,避免重复计算。当窗口向右移动时,只需要移除左边的元素,添加右边的元素。
Java实现
java
import java.util.*;
public class Solution2 {
public static int findMaxColorCount(int[] cars, int windowSize) {
int n = cars.length;
if (windowSize > n) return 0;
int maxCount = 0;
int[] colorCount = new int[3]; // 0, 1, 2三种颜色
// 初始化第一个窗口
for (int i = 0; i < windowSize; i++) {
colorCount[cars[i]]++;
}
// 计算第一个窗口的最大值
maxCount = Math.max(colorCount[0], Math.max(colorCount[1], colorCount[2]));
// 滑动窗口
for (int i = windowSize; i < n; i++) {
// 移除窗口左边的元素
colorCount[cars[i - windowSize]]--;
// 添加窗口右边的元素
colorCount[cars[i]]++;
// 更新最大值
int currentMax = Math.max(colorCount[0], Math.max(colorCount[1], colorCount[2]));
maxCount = Math.max(maxCount, currentMax);
}
return maxCount;
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String[] input = scanner.nextLine().split(" ");
int[] cars = new int[input.length];
for (int i = 0; i < input.length; i++) {
cars[i] = Integer.parseInt(input[i]);
}
int windowSize = scanner.nextInt();
System.out.println(findMaxColorCount(cars, windowSize));
}
}
Python实现
python
def find_max_color_count(cars, window_size):
n = len(cars)
if window_size > n:
return 0
max_count = 0
color_count = [0, 0, 0] # 0, 1, 2三种颜色
# 初始化第一个窗口
for i in range(window_size):
color_count[cars[i]] += 1
# 计算第一个窗口的最大值
max_count = max(color_count)
# 滑动窗口
for i in range(window_size, n):
# 移除窗口左边的元素
color_count[cars[i - window_size]] -= 1
# 添加窗口右边的元素
color_count[cars[i]] += 1
# 更新最大值
current_max = max(color_count)
max_count = max(max_count, current_max)
return max_count
# 输入处理
cars = list(map(int, input().split()))
window_size = int(input())
print(find_max_color_count(cars, window_size))
C++实现
cpp
#include <iostream>
#include <vector>
#include <algorithm>
#include <sstream>
using namespace std;
int findMaxColorCount(vector<int>& cars, int windowSize) {
int n = cars.size();
if (windowSize > n) return 0;
int maxCount = 0;
vector<int> colorCount(3, 0); // 0, 1, 2三种颜色
// 初始化第一个窗口
for (int i = 0; i < windowSize; i++) {
colorCount[cars[i]]++;
}
// 计算第一个窗口的最大值
maxCount = *max_element(colorCount.begin(), colorCount.end());
// 滑动窗口
for (int i = windowSize; i < n; i++) {
// 移除窗口左边的元素
colorCount[cars[i - windowSize]]--;
// 添加窗口右边的元素
colorCount[cars[i]]++;
// 更新最大值
int currentMax = *max_element(colorCount.begin(), colorCount.end());
maxCount = max(maxCount, currentMax);
}
return maxCount;
}
int main() {
string line;
getline(cin, line);
istringstream iss(line);
vector<int> cars;
int num;
while (iss >> num) {
cars.push_back(num);
}
int windowSize;
cin >> windowSize;
cout << findMaxColorCount(cars, windowSize) << endl;
return 0;
}
复杂度分析
解法一(暴力解法)
- 时间复杂度:O(n × m),其中n是车辆数组长度,m是窗口大小
- 空间复杂度:O(1),只使用了固定大小的数组
解法二(滑动窗口)
- 时间复杂度:O(n),其中n是车辆数组长度
- 空间复杂度:O(1),只使用了固定大小的数组
总结
这道题考查的是滑动窗口的经典应用。解法二通过优化避免了重复计算,将时间复杂度从O(n×m)降低到O(n),在处理大数据量时效果更佳。
关键点:
- 理解滑动窗口的概念
- 正确处理窗口边界
- 高效地维护窗口内的统计信息
这类问题在实际开发中经常遇到,掌握滑动窗口技巧对解决类似问题很有帮助。