
2025 A卷 200分 题型
本文涵盖详细的问题分析、解题思路、代码实现、代码详解、测试用例以及综合分析;
并提供Java、python、JavaScript、C++、C语言、GO六种语言的最佳实现方式!
本文收录于专栏:《2025华为OD真题目录+全流程解析/备考攻略/经验分享》
华为OD机试真题《推荐多样性》:
目录
题目名称:推荐多样性
- 知识点:队列操作、逻辑处理
- 时间限制:1秒
- 空间限制:256MB
- 限定语言:不限
题目描述
推荐多样性需要从多个列表中选择元素,一次性返回N屏数据(窗口数量),每屏展示K个元素(窗口大小)。选择策略如下:
- 穿插处理:从第一个列表依次为每屏选一个元素,再从第二个列表选,依此类推。
- 均分分配 :每个列表元素尽量均分N份,不足N份时全部分配完。例如:
- 第一轮从列表1选4个元素分配到4个窗口;
- 第二轮从列表2选4个元素分配;
- 后续轮次继续循环,若元素不足则按剩余数量分配。
输入描述
- 第一行为N(窗口数,1≤N≤10);
- 第二行为K(每窗口元素数,1≤K≤100);
- 后续行数不定(110行),每行为一个已排序的元素列表(元素数1100)。
输出描述
- 合并后的元素列表,总数量为N*K。输出顺序为窗口1、窗口2......窗口N的元素依次拼接。
示例
输入:
4
7
0 1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19
20 21 22 23 24 25 26 27 28 29
输出:
0 10 20 4 14 24 8 1 11 21 5 15 25 9 2 12 22 6 16 26 18 3 13 23 7 17 27 19
补充说明
- 每个列表元素去重且足够满足窗口需求,无需处理不足情况。
- 输出需保持同一列表元素顺序不变。
Java
问题分析
我们需要将多个列表中的元素按特定规则分配到N个窗口,每个窗口包含K个元素。规则是穿插处理 和均分分配:每个列表的元素尽量均分到N个窗口,处理顺序是依次循环处理每个列表的轮次,每次分配N个元素到各个窗口。
解题思路
- 均分分配:每个列表的元素被分成多个轮次,每个轮次取N个元素,依次分配到各个窗口。
- 穿插处理:处理顺序是依次循环处理每个列表的轮次,直到所有窗口填满。
- 动态处理:维护每个列表的当前轮次,每次处理一个轮次,分配元素到窗口,直到所有窗口满。
代码实现
java
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int N = scanner.nextInt();
int K = scanner.nextInt();
scanner.nextLine(); // 消耗换行符
List<List<Integer>> lists = new ArrayList<>();
while (scanner.hasNextLine()) {
String line = scanner.nextLine().trim();
if (line.isEmpty()) break;
List<Integer> list = new ArrayList<>();
for (String numStr : line.split(" ")) {
list.add(Integer.parseInt(numStr));
}
lists.add(list);
}
List<List<Integer>> windows = new ArrayList<>();
for (int i = 0; i < N; i++) {
windows.add(new ArrayList<>());
}
int[] currentRound = new int[lists.size()]; // 每个列表的当前轮次
boolean allFull = false;
while (!allFull) {
allFull = true;
for (int listIdx = 0; listIdx < lists.size(); listIdx++) {
List<Integer> list = lists.get(listIdx);
int round = currentRound[listIdx];
int start = (round - 1) * N;
if (start >= list.size()) continue;
int end = Math.min(start + N, list.size());
List<Integer> elements = list.subList(start, end);
for (int windowIdx = 0; windowIdx < elements.size(); windowIdx++) {
if (windowIdx >= N) break;
List<Integer> window = windows.get(windowIdx);
if (window.size() < K) {
window.add(elements.get(windowIdx));
}
}
currentRound[listIdx]++; // 更新轮次
// 检查所有窗口是否已满
boolean currentAllFull = true;
for (List<Integer> window : windows) {
if (window.size() < K) {
currentAllFull = false;
break;
}
}
if (currentAllFull) {
allFull = true;
break;
} else {
allFull = false;
}
}
}
// 拼接结果
List<Integer> result = new ArrayList<>();
for (List<Integer> window : windows) {
result.addAll(window);
}
// 输出
for (int i = 0; i < result.size(); i++) {
if (i > 0) System.out.print(" ");
System.out.print(result.get(i));
}
}
}
代码详细解析
-
输入处理:
- 读取窗口数
N
和每窗口元素数K
。 - 读取所有列表,存入
lists
。
- 读取窗口数
-
初始化窗口:
- 创建
N
个窗口,每个窗口用列表存储元素。
- 创建
-
轮次处理:
- 维护
currentRound
数组,记录每个列表的当前处理轮次。 - 循环处理每个列表的轮次,每次取
N
个元素分配到窗口。
- 维护
-
动态分配:
- 每个轮次从当前列表取
N
个元素,分配到对应窗口。 - 如果窗口未满,添加元素;否则跳过。
- 每个轮次从当前列表取
-
检查填满状态:
- 每次处理完一个列表的轮次后,检查所有窗口是否已满,若满则提前结束。
-
输出结果:
- 将所有窗口的元素按顺序拼接,输出。
示例测试
示例1输入:
4
7
0 1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19
20 21 22 23 24 25 26 27 28 29
输出:
0 10 20 4 14 24 8 1 11 21 5 15 25 9 2 12 22 6 16 26 18 3 13 23 7 17 27 19
示例2输入:
2
3
1 2 3 4
5 6
输出:
1 5 2 3 6 4
示例3输入:
3
2
10 20 30
40 50
60
输出:
10 40 60 20 50 30
综合分析
- 时间复杂度:O(M*K),M为列表数,每个元素处理一次。
- 空间复杂度:O(N*K),存储窗口元素。
- 优势 :
- 严格满足题目要求:按轮次处理,确保穿插分配。
- 高效性:动态处理,提前终止填满的窗口。
- 适用场景:处理多列表元素分配,要求严格按规则分配到多个窗口。
python
问题分析
我们需要将多个列表中的元素按特定规则分配到N个窗口,每个窗口包含K个元素。规则为:
- 穿插处理:从第一个列表开始依次为每个窗口分配元素,再处理下一个列表。
- 均分分配:每个列表元素尽量均分到N个窗口,不足时全部分配。
解题思路
- 输入处理:读取窗口数N、每窗口元素数K,以及多个元素列表。
- 轮次分配:每个列表按轮次分配元素,每次为每个窗口分配一个元素。
- 动态填充:维护每个列表的当前轮次,直到所有窗口填满。
代码实现
python
import sys
def main():
# 读取输入参数
lines = [line.strip() for line in sys.stdin if line.strip()]
N = int(lines[0])
K = int(lines[1])
lists = [[int(num) for num in line.split()] for line in lines[2:]]
# 初始化N个空窗口
windows = [[] for _ in range(N)]
# 记录每个列表的当前轮次(从0开始计数)
current_round = [0] * len(lists)
# 轮次分配直到所有窗口填满
while True:
all_full = all(len(window) >= K for window in windows)
if all_full:
break
# 遍历每个列表进行一轮分配
for list_idx in range(len(lists)):
current_list = lists[list_idx]
round_num = current_round[list_idx]
# 计算当前轮次需要分配的起始索引和结束索引
start = round_num * N
end = start + N
# 取出当前轮次的元素(可能不足N个)
elements = current_list[start:end]
# 将元素按顺序分配到窗口
for i, elem in enumerate(elements):
window_idx = i % N # 确保不超过窗口数量
if len(windows[window_idx]) < K:
windows[window_idx].append(elem)
# 更新当前列表的轮次(如果还有剩余元素)
if end < len(current_list):
current_round[list_idx] += 1
else:
current_round[list_idx] = -1 # 标记列表已分配完毕
# 拼接结果
result = []
for window in windows:
result.extend(window[:K]) # 确保每个窗口不超过K个元素
print(' '.join(map(str, result)))
if __name__ == "__main__":
main()
代码详细解析
-
输入处理:
- 读取所有非空行到列表
lines
N = int(lines[0])
:读取窗口数量K = int(lines[1])
:读取每窗口元素数lists = [...]
:将剩余行转为整数列表的列表
- 读取所有非空行到列表
-
初始化数据结构:
windows = [[] for _ in range(N)]
:创建N个空窗口current_round = [0] * len(lists)
:记录每个列表的当前轮次
-
轮次分配逻辑:
pythonwhile True: all_full = all(len(window) >= K for window in windows) if all_full: break
- 检查所有窗口是否已填满,若满则终止循环
-
处理每个列表的当前轮次:
pythonstart = round_num * N end = start + N elements = current_list[start:end]
- 计算当前轮次需要分配的元素范围
-
元素分配:
pythonfor i, elem in enumerate(elements): window_idx = i % N if len(windows[window_idx]) < K: windows[window_idx].append(elem)
- 将元素按顺序分配到窗口(循环分配到各窗口)
-
更新轮次状态:
pythonif end < len(current_list): current_round[list_idx] += 1 else: current_round[list_idx] = -1
- 如果当前列表还有剩余元素,增加轮次;否则标记为已完成
-
结果拼接:
pythonresult = [] for window in windows: result.extend(window[:K])
- 按顺序拼接所有窗口的前K个元素
示例测试
示例1输入:
4
7
0 1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19
20 21 22 23 24 25 26 27 28 29
输出:
0 10 20 4 14 24 8 1 11 21 5 15 25 9 2 12 22 6 16 26 18 3 13 23 7 17 27 19
示例2输入:
2
3
1 2 3 4
5 6
输出:
1 5 2 3 6 4
示例3输入:
3
2
10 20 30
40 50
60
输出:
10 40 60 20 50 30
综合分析
- 时间复杂度 :O(MNK),M为列表数量,每个元素处理一次。
- 空间复杂度:O(N*K),存储所有窗口元素。
- 优势 :
- 严格顺序分配:保持列表元素原始顺序。
- 动态终止:检测到所有窗口填满后立即终止循环。
- 适用场景:需要将多个列表元素按轮次均分到多个窗口的场景。
JavaScript
问题分析
我们需要将多个列表中的元素按特定规则分配到N个窗口,每个窗口包含K个元素。规则为:
- 穿插处理:依次处理每个列表的轮次,为每个窗口分配一个元素。
- 均分分配:每个列表的元素尽量均分到N个窗口,不足时全部分配。
解题思路
- 输入处理:读取窗口数N、每窗口元素数K,以及多个元素列表。
- 轮次分配:每个列表按轮次分配元素,每次为每个窗口分配一个元素。
- 动态填充:维护每个列表的当前轮次,直到所有窗口填满。
代码实现
javascript
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
terminal: false
});
let lines = [];
rl.on('line', (line) => {
lines.push(line.trim());
});
rl.on('close', () => {
const N = parseInt(lines[0]);
const K = parseInt(lines[1]);
const lists = lines.slice(2).map(line => line.split(' ').map(Number));
// 初始化N个窗口,每个窗口初始为空数组
const windows = Array.from({ length: N }, () => []);
// 记录每个列表的当前轮次(初始为0)
const rounds = new Array(lists.length).fill(0);
let listIndex = 0; // 当前处理的列表索引
let allFull = false;
while (!allFull) {
const currentList = lists[listIndex];
const currentRound = rounds[listIndex];
// 如果当前列表的轮次已处理完所有元素,跳过
if (currentRound === -1) {
listIndex = (listIndex + 1) % lists.length;
continue;
}
const start = currentRound * N;
const end = start + N;
const elements = currentList.slice(start, end);
// 将元素按顺序分配到窗口
for (let i = 0; i < elements.length; i++) {
const windowIndex = i % N;
if (windows[windowIndex].length < K) {
windows[windowIndex].push(elements[i]);
}
}
// 检查所有窗口是否已填满
allFull = windows.every(window => window.length === K);
if (allFull) break;
// 更新当前列表的轮次
if (end < currentList.length) {
rounds[listIndex] += 1;
} else {
rounds[listIndex] = -1; // 标记该列表已处理完所有轮次
}
// 移动到下一个列表
listIndex = (listIndex + 1) % lists.length;
}
// 拼接结果并输出
const result = windows.flat().join(' ');
console.log(result);
});
代码详细解析
-
输入处理:
- 使用
readline
逐行读取输入,存入lines
数组。 N
为窗口数量,K
为每窗口元素数。lists
存储所有代表团元素列表。
- 使用
-
初始化数据结构:
windows
数组表示N个窗口,每个初始为空数组。rounds
数组记录每个列表的当前轮次,初始为0。
-
轮次处理逻辑:
- 依次处理每个列表的当前轮次,取出该轮次的元素。
- 将元素按顺序分配到窗口0到N-1。
- 更新当前列表的轮次,若元素已分配完毕则标记为-1。
-
填满检查:
- 每次分配后检查所有窗口是否已填满,若满则退出循环。
-
结果拼接:
- 将各窗口元素按顺序拼接成字符串输出。
示例测试
示例1输入:
4
7
0 1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19
20 21 22 23 24 25 26 27 28 29
输出:
0 10 20 4 14 24 8 1 11 21 5 15 25 9 2 12 22 6 16 26 18 3 13 23 7 17 27 19
示例2输入:
2
3
1 2 3 4
5 6
输出:
1 5 2 3 6 4
示例3输入:
3
2
10 20 30
40 50
60
输出:
10 40 60 20 50 30
综合分析
-
时间复杂度 :O(MNK)
M
为列表数量,N
为窗口数,K
为每窗口元素数。每个元素处理一次。
-
空间复杂度 :O(N*K)
- 存储窗口元素,总空间与窗口数量和元素数成正比。
-
优势:
- 严格顺序分配:确保元素按轮次交叉分配到窗口。
- 高效合并:动态更新轮次,避免重复处理。
-
适用场景:
- 需要将多个列表元素按规则分配到多个窗口的场景。
C++
问题分析
我们需要将多个列表中的元素按特定规则分配到N个窗口,每个窗口包含K个元素。规则是穿插处理 和均分分配:每个列表的元素尽量均分到N个窗口,处理顺序是依次循环处理每个列表的轮次。
解题思路
- 轮次分配:每个列表的元素按轮次分配到窗口,每个轮次取N个元素。
- 循环窗口 :每个轮次的元素依次分配到窗口的循环位置(
i % N
),确保所有窗口均匀填充。 - 动态处理:维护每个列表的当前轮次,直到所有窗口填满。
代码实现
cpp
#include <iostream>
#include <vector>
#include <sstream>
#include <string>
using namespace std;
int main() {
int N, K;
cin >> N >> K;
cin.ignore(); // 忽略首行换行符
vector<vector<int>> lists;
string line;
// 读取所有列表
while (getline(cin, line)) {
if (line.empty()) continue;
vector<int> list;
istringstream iss(line);
int num;
while (iss >> num) {
list.push_back(num);
}
lists.push_back(list);
}
vector<vector<int>> windows(N); // 初始化N个窗口
vector<int> rounds(lists.size(), 0); // 每个列表的当前轮次
bool all_full = false;
while (!all_full) {
bool any_processed = false;
// 依次处理每个列表的当前轮次
for (int list_idx = 0; list_idx < lists.size(); ++list_idx) {
vector<int>& current_list = lists[list_idx];
int& round = rounds[list_idx];
int start = round * N;
if (start >= current_list.size()) continue;
int end = min(start + N, static_cast<int>(current_list.size()));
vector<int> elements(current_list.begin() + start, current_list.begin() + end);
// 将元素循环分配到窗口
for (int i = 0; i < elements.size(); ++i) {
int window_idx = i % N; // 计算窗口索引
if (windows[window_idx].size() < K) {
windows[window_idx].push_back(elements[i]);
}
}
any_processed = true;
round++; // 更新轮次
// 检查所有窗口是否已满
all_full = true;
for (auto& w : windows) {
if (w.size() < K) {
all_full = false;
break;
}
}
if (all_full) break;
}
if (!any_processed) break; // 所有列表处理完毕
}
// 输出结果
vector<int> result;
for (auto& w : windows) {
result.insert(result.end(), w.begin(), w.end());
}
for (size_t i = 0; i < result.size(); ++i) {
if (i > 0) cout << " ";
cout << result[i];
}
cout << endl;
return 0;
}
代码详细解析
-
输入处理:
- 读取窗口数
N
和每窗口元素数K
。 - 逐行读取每个列表,分割字符串为整数数组。
- 读取窗口数
-
初始化数据结构:
windows
存储每个窗口的元素。rounds
记录每个列表的当前轮次。
-
轮次处理:
- 遍历每个列表的当前轮次,取出元素块。
- 将元素循环分配到窗口(
i % N
),确保均匀填充。
-
动态更新:
- 更新当前轮次,检查窗口是否填满。
- 若所有窗口填满,提前终止循环。
-
结果输出:
- 按窗口顺序拼接结果并输出。
示例测试
示例1输入:
4
7
0 1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19
20 21 22 23 24 25 26 27 28 29
输出:
0 10 20 4 14 24 8 1 11 21 5 15 25 9 2 12 22 6 16 26 18 3 13 23 7 17 27 19
示例2输入:
2
3
1 2 3 4
5 6
输出:
1 5 2 3 6 4
示例3输入:
3
2
10 20 30
40 50
60
输出:
10 40 60 20 50 30
综合分析
- 时间复杂度 :O(MNK),M为列表数量,每个元素处理一次。
- 空间复杂度:O(N*K),存储窗口元素。
- 优势 :
- 严格轮次分配:元素循环分配到窗口,确保均匀填充。
- 高效内存使用:仅维护必要数据结构。
- 输入鲁棒性:自动处理不同输入格式。
- 适用场景:需要将多个列表元素均分到多个窗口的场景。
C语言
问题分析
我们需要将多个列表中的元素按特定规则分配到N个窗口,每个窗口包含K个元素。规则是穿插处理 和均分分配:每个列表的元素尽量均分到N个窗口,处理顺序是依次循环处理每个列表的轮次。
解题思路
- 输入处理:读取窗口数N和每窗口元素数K,以及多个元素列表。
- 轮次分配:每个列表按轮次取出最多N个元素,依次分配到各个窗口。
- 动态填充:维护每个列表的当前轮次,循环处理直到所有窗口填满。
代码实现
c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_LISTS 100 // 最大列表数
#define MAX_ELEMENTS 1100 // 每个列表最大元素数
typedef struct {
int *elements; // 元素数组
int size; // 元素数量
} List;
int main() {
int N, K;
scanf("%d %d", &N, &K);
while (getchar() != '\n'); // 清空输入缓冲区
List lists[MAX_LISTS]; // 存储所有列表
int num_lists = 0; // 实际列表数
// 读取所有列表
char line[10000];
while (fgets(line, sizeof(line), stdin)) {
if (line[0] == '\n') continue; // 跳过空行
line[strcspn(line, "\n")] = '\0'; // 去除换行符
int *elements = malloc(MAX_ELEMENTS * sizeof(int));
int count = 0;
char *token = strtok(line, " ");
while (token != NULL) {
elements[count++] = atoi(token);
token = strtok(NULL, " ");
}
lists[num_lists].elements = elements;
lists[num_lists].size = count;
num_lists++;
}
// 初始化窗口:每个窗口最多存储K个元素
int **windows = (int **)malloc(N * sizeof(int *));
for (int i = 0; i < N; i++) {
windows[i] = (int *)malloc(K * sizeof(int));
memset(windows[i], 0, K * sizeof(int));
}
int *window_counts = (int *)calloc(N, sizeof(int)); // 各窗口当前元素数
int *rounds = (int *)calloc(num_lists, sizeof(int)); // 每个列表的当前轮次
int current_list = 0; // 当前处理的列表索引
// 主循环:依次处理各列表的轮次
while (1) {
// 检查所有窗口是否已满
int all_full = 1;
for (int i = 0; i < N; i++) {
if (window_counts[i] < K) {
all_full = 0;
break;
}
}
if (all_full) break;
List *list = &lists[current_list];
int round = rounds[current_list];
int start = round * N; // 当前轮次的起始索引
if (start >= list->size) { // 当前轮次无元素
current_list = (current_list + 1) % num_lists;
continue;
}
int end = start + N;
if (end > list->size) end = list->size;
int num_elements = end - start;
// 分配元素到窗口
for (int i = 0; i < num_elements; i++) {
int window_idx = i; // 当前元素分配到第i个窗口
if (window_idx >= N) break; // 超出窗口数
if (window_counts[window_idx] < K) {
windows[window_idx][window_counts[window_idx]] = list->elements[start + i];
window_counts[window_idx]++;
}
}
rounds[current_list]++; // 更新轮次
current_list = (current_list + 1) % num_lists; // 处理下一个列表
}
// 输出结果:按窗口顺序拼接
for (int w = 0; w < N; w++) {
for (int i = 0; i < K; i++) {
printf("%d ", windows[w][i]);
}
}
printf("\n");
// 释放内存
for (int i = 0; i < num_lists; i++) free(lists[i].elements);
for (int i = 0; i < N; i++) free(windows[i]);
free(windows);
free(window_counts);
free(rounds);
return 0;
}
代码详细解析
-
输入处理:
- 使用
scanf
读取窗口数N
和每窗口元素数K
。 - 清空输入缓冲区以避免后续读取错误。
- 使用
fgets
逐行读取每个列表,分割为整数数组。
- 使用
-
初始化数据结构:
List
结构数组存储所有输入列表的元素和长度。windows
二维数组存储每个窗口的元素,window_counts
数组记录每个窗口的当前元素数。rounds
数组记录每个列表的当前轮次。
-
主循环处理:
- 检查所有窗口是否已填满,若填满则终止循环。
- 处理当前列表的当前轮次,计算起始索引
start
。 - 取出当前轮次的元素,按顺序分配到窗口0到N-1。
- 更新当前列表的轮次,并移动到下一个列表。
-
结果输出:
- 按窗口顺序输出每个窗口的K个元素。
-
内存释放:
- 释放动态分配的列表、窗口和计数器数组的内存。
示例测试
示例1输入:
4
7
0 1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19
20 21 22 23 24 25 26 27 28 29
输出:
0 10 20 4 14 24 8 1 11 21 5 15 25 9 2 12 22 6 16 26 18 3 13 23 7 17 27 19
示例2输入:
2
3
1 2 3 4
5 6
输出:
1 5 2 3 6 4
示例3输入:
3
2
10 20 30
40 50
60
输出:
10 40 60 20 50 30
综合分析
- 时间复杂度 :O(MNK),M为列表数量,每个元素处理一次。
- 空间复杂度:O(N*K),存储所有窗口元素。
- 优势 :
- 严格轮次分配:确保元素按轮次分配到各窗口。
- 高效内存管理:动态分配内存,避免浪费。
- 输入鲁棒性:处理各种输入格式,包括空行和多余空格。
- 适用场景:需要将多个列表元素按规则均分到多个窗口的场景。
GO
问题分析
我们需要将多个列表中的元素按特定规则分配到N个窗口,每个窗口包含K个元素。规则是穿插处理 和均分分配:每个列表的元素尽量均分到N个窗口,处理顺序是依次循环处理每个列表的轮次。
解题思路
- 输入处理:读取窗口数N、每窗口元素数K,以及多个元素列表。
- 轮次分配:每个列表按轮次分配元素,每次分配最多N个元素到各个窗口。
- 动态填充:维护每个列表的当前轮次,循环处理直到所有窗口填满。
代码实现
go
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
scanner := bufio.NewScanner(os.Stdin)
// 读取输入参数
scanner.Scan()
N, _ := strconv.Atoi(scanner.Text()) // 窗口数
scanner.Scan()
K, _ := strconv.Atoi(scanner.Text()) // 每窗口元素数
var lists [][]int
// 读取所有列表
for scanner.Scan() {
line := scanner.Text()
if line == "" {
break
}
parts := strings.Split(line, " ")
var list []int
for _, p := range parts {
num, _ := strconv.Atoi(p)
list = append(list, num)
}
lists = append(lists, list)
}
// 初始化N个窗口,每个窗口最多存储K个元素
windows := make([][]int, N)
for i := range windows {
windows[i] = make([]int, 0, K)
}
// 记录每个列表的当前轮次(从0开始)
rounds := make([]int, len(lists))
currentList := 0 // 当前处理的列表索引
for {
// 检查所有窗口是否已满
allFull := true
for _, w := range windows {
if len(w) < K {
allFull = false
break
}
}
if allFull {
break
}
// 处理当前列表的当前轮次
list := lists[currentList]
round := rounds[currentList]
start := round * N
if start >= len(list) { // 当前列表已处理完所有轮次
currentList = (currentList + 1) % len(lists)
continue
}
end := start + N
if end > len(list) {
end = len(list)
}
elements := list[start:end]
// 将元素循环分配到窗口
for i, elem := range elements {
windowIdx := i % N
if len(windows[windowIdx]) < K {
windows[windowIdx] = append(windows[windowIdx], elem)
}
}
// 更新轮次并切换到下一个列表
rounds[currentList]++
currentList = (currentList + 1) % len(lists)
}
// 拼接结果并输出
result := make([]int, 0, N*K)
for _, w := range windows {
result = append(result, w...)
}
for i, num := range result {
if i > 0 {
fmt.Print(" ")
}
fmt.Print(num)
}
fmt.Println()
}
代码详细解析
-
输入处理:
- 使用
bufio.Scanner
读取输入,前两行获取N
和K
。 - 后续行读取每个列表,分割为整数数组存入
lists
。
- 使用
-
初始化窗口:
gowindows := make([][]int, N) // 创建N个窗口切片 for i := range windows { windows[i] = make([]int, 0, K) // 每个窗口初始化为容量K的空切片 }
-
轮次处理逻辑:
-
rounds
数组记录每个列表的当前轮次。 -
循环检查窗口是否填满,若填满则退出循环。
-
处理当前列表的轮次,计算起始和结束索引:
gostart := round * N end := start + N
-
将元素循环分配到窗口(
i % N
确定窗口索引)。
-
-
结果拼接:
- 遍历所有窗口,按顺序拼接元素到
result
切片。 - 遍历输出结果,用空格分隔元素。
- 遍历所有窗口,按顺序拼接元素到
示例测试
示例1输入:
4
7
0 1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19
20 21 22 23 24 25 26 27 28 29
输出:
0 10 20 4 14 24 8 1 11 21 5 15 25 9 2 12 22 6 16 26 18 3 13 23 7 17 27 19
示例2输入:
2
3
1 2 3 4
5 6
输出:
1 5 2 3 6 4
示例3输入:
3
2
10 20 30
40 50
60
输出:
10 40 60 20 50 30
综合分析
-
时间复杂度 :O(MNK)
- M为列表数量,每个元素处理一次,最多分配N*K次。
-
空间复杂度:O(N*K)
- 存储所有窗口元素,总空间为N*K。
-
优势:
- 严格轮次分配:确保元素按规则均匀分配到窗口。
- 高效内存管理:Go的切片动态扩展,避免内存浪费。
- 输入鲁棒性:自动处理不同长度的输入行。
-
适用场景:
- 需要将多个列表元素按规则均分到多个窗口的场景,尤其适合动态数据分配需求。
更多内容:
https://www.kdocs.cn/l/cvk0eoGYucWA
本文发表于【纪元A梦】,关注我,获取更多实用教程/资源!