【2024年华为OD机试】(C卷,200分)- 推荐多样性 (JavaScriptJava PythonC/C++)

在这里插入图片描述

一、问题描述

问题描述

我们需要从多个已排序的列表中选取元素,以填充多个窗口。每个窗口需要展示一定数量的元素,且元素的选择需要遵循特定的穿插策略。具体来说,我们需要:

  1. 从第一个列表中为每个窗口选择一个元素,然后从第二个列表中为每个窗口选择一个元素,依此类推。
  2. 每个列表的元素应尽量均分到所有窗口中。如果某个列表的元素不足以均分到所有窗口,则应将剩余元素全部分配到前面的窗口中。
  3. 最终输出的元素列表应按照窗口顺序排列,即先输出第一个窗口的所有元素,再输出第二个窗口的所有元素,依此类推。

输入输出描述

输入

  • 第一行输入为 N,表示需要输出的窗口数量,取值范围为 [1, 10]
  • 第二行输入为 K,表示每个窗口需要的元素数量,取值范围为 [1, 100]
  • 之后的行数不定(行数取值范围为 [1, 10]),表示每个列表输出的元素列表。元素之间以空格隔开,已经过排序处理,每个列表输出的元素数量取值范围为 [1, 100]

输出

  • 输出元素列表,元素数量为 窗口数量 * 窗口大小,元素之间以空格分隔。多个窗口合并为一个列表输出,先输出窗口1的元素列表,再输出窗口2的元素列表,依此类推。

解题思路

我们可以将最终的窗口集视为一个矩阵 windows,该矩阵有 KN 列,矩阵的每一列对应一个窗口。最终按列打印该矩阵,即为题解。

填充策略

  1. 初始化:创建一个大小为 K * N 的一维数组 windows,用于存储最终的元素列表。
  2. 填充过程
    • 从第一个列表开始,依次为每个窗口选择一个元素。
    • 如果当前列表的元素不足以分配给所有窗口,则从下一个列表中“借”元素来补充。
    • 每次填充后,更新指针 idx,指向下一个需要填充的位置。
  3. 特殊情况处理
    • 如果某个列表的元素不足以分配给所有窗口,则需要从下一个列表中“借”元素。此时,需要确保存在下一个列表,否则无法继续填充。

示例解析

以题目中的示例为例:

输入

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

解析

  1. 从第一个列表中选择 4 条元素 0 1 2 3,分别放到 4 个窗口中。
  2. 从第二个列表中选择 4 条元素 10 11 12 13,分别放到 4 个窗口中。
  3. 从第三个列表中选择 4 条元素 20 21 22 23,分别放到 4 个窗口中。
  4. 再次从第一个列表中选择 4 条元素 4 5 6 7,分别放到 4 个窗口中。
  5. 从第一个列表中选择剩下的 2 条元素 8 9,分别放到窗口1和窗口2。
  6. 从第二个列表中选择剩下的 2 条元素 18 19,分别放到窗口3和窗口4。

最终输出的元素列表按照窗口顺序排列,即先输出窗口1的所有元素,再输出窗口2的所有元素,依此类推。

总结

通过将窗口集视为一个矩阵,并按照特定的填充策略依次从各个列表中选择元素,我们可以有效地解决这个问题。关键在于正确处理元素不足时的“借”元素操作,并确保最终输出的元素列表按照窗口顺序排列。

二、JavaScript算法源码


代码结构

  1. 输入处理

    • 使用 readline 模块读取输入数据。
    • 解析窗口数量 n 和每个窗口的元素数量 k
    • 读取多个列表,并将每个列表转换为数字数组,存储在 lists 中。
  2. 窗口矩阵填充

    • 创建一个一维数组 windows,用于模拟 kn 列的窗口矩阵。
    • 使用指针 idx 记录当前填充的位置。
    • 使用变量 level 记录当前从哪个列表中取值。
  3. 填充逻辑

    • 从当前列表 lists[level] 中取出 n 个元素,依次填充到 windows 中。
    • 如果当前列表元素不足,则从下一个列表中“借”元素。
    • 更新指针 idxlevel,确保填充过程正确。
  4. 输出结果

    • 按列遍历 windows 矩阵,将元素按窗口顺序收集到 ans 数组中。
    • 最终输出 ans,元素之间用空格分隔。

代码逐行注释

const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;void (async function () {// 读取窗口数量 nconst n = parseInt(await readline());// 读取每个窗口的元素数量 kconst k = parseInt(await readline());// 存储所有列表const lists = [];// 循环读取输入,直到输入结束while (true) {try {// 读取一行输入const s = await readline();// 如果输入为空,结束读取if (s.length == 0) break;// 将输入行按空格分割,转换为数字数组,并存入 listslists.push(s.split(" ").map(Number));} catch (e) {// 捕获异常(如输入结束),退出循环break;}}// 创建一个大小为 k * n 的一维数组,用于模拟窗口矩阵const windows = new Array(k * n);// 当前填充位置的索引let idx = 0;// 当前从第 level 个列表中取值let level = 0;// 当窗口矩阵未填满时,继续填充while (idx < windows.length) {// 标记当前轮次是否发生了“借”动作let flag = false;// 从当前列表 lists[level] 中取 n 个元素for (let i = 0; i < n; i++) {// 将列表的第一个元素取出,放入 windows 中windows[idx++] = lists[level].shift();// 如果当前列表为空且还有其他列表,则从下一个列表中“借”元素if (lists[level].length == 0 && lists.length > 1) {// 删除当前空列表lists.splice(level, 1);// 防止 level 越界level %= lists.length;// 标记发生了“借”动作flag = true;}}// 如果没有发生“借”动作,则切换到下一个列表if (!flag) {level = (level + 1) % lists.length; // 防止越界}}// 用于存储最终结果的数组const ans = [];// 按列遍历窗口矩阵for (let j = 0; j < n; j++) {// 按行遍历窗口矩阵for (let i = 0; i < k; i++) {// 按列收集元素,存入 ansans.push(windows[i * n + j]);}}// 输出结果,元素之间用空格分隔console.log(ans.join(" "));
})();

代码逻辑详解

1. 输入处理
  • 使用 readline 模块逐行读取输入。
  • 第一行读取窗口数量 n,第二行读取每个窗口的元素数量 k
  • 后续行读取每个列表,并将其转换为数字数组,存储在 lists 中。
2. 窗口矩阵填充
  • 创建一个大小为 k * n 的一维数组 windows,用于模拟窗口矩阵。
  • 使用指针 idx 记录当前填充的位置。
  • 使用变量 level 记录当前从哪个列表中取值。
3. 填充逻辑
  • 从当前列表 lists[level] 中取出 n 个元素,依次填充到 windows 中。
  • 如果当前列表元素不足,则从下一个列表中“借”元素,并删除当前空列表。
  • 更新指针 idxlevel,确保填充过程正确。
4. 输出结果
  • 按列遍历 windows 矩阵,将元素按窗口顺序收集到 ans 数组中。
  • 最终输出 ans,元素之间用空格分隔。

示例运行

输入
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
解析
  • 从第一个列表中选择 4 条元素 0 1 2 3,分别放到 4 个窗口中。
  • 从第二个列表中选择 4 条元素 10 11 12 13,分别放到 4 个窗口中。
  • 从第三个列表中选择 4 条元素 20 21 22 23,分别放到 4 个窗口中。
  • 再次从第一个列表中选择 4 条元素 4 5 6 7,分别放到 4 个窗口中。
  • 从第一个列表中选择剩下的 2 条元素 8 9,分别放到窗口1和窗口2。
  • 从第二个列表中选择剩下的 2 条元素 18 19,分别放到窗口3和窗口4。

最终输出的元素列表按照窗口顺序排列。


通过以上注释和讲解,你应该能够理解代码的每一部分功能和实现逻辑。如果还有疑问,欢迎随时提问!

三、Java算法源码


代码结构

  1. 输入处理

    • 使用 Scanner 读取输入数据。
    • 解析窗口数量 n 和每个窗口的元素数量 k
    • 读取多个列表,并将每个列表转换为 LinkedList<Integer>,存储在 lists 中。
  2. 窗口矩阵填充

    • 创建一个一维数组 windows,用于模拟 kn 列的窗口矩阵。
    • 使用指针 idx 记录当前填充的位置。
    • 使用变量 level 记录当前从哪个列表中取值。
  3. 填充逻辑

    • 从当前列表 lists.get(level) 中取出 n 个元素,依次填充到 windows 中。
    • 如果当前列表元素不足,则从下一个列表中“借”元素。
    • 更新指针 idxlevel,确保填充过程正确。
  4. 输出结果

    • 使用 StringJoiner 按列遍历 windows 矩阵,将元素按窗口顺序拼接成字符串。
    • 最终输出结果。

代码逐行注释

import java.util.*;public class Main {public static void main(String[] args) {// 创建 Scanner 对象,用于读取输入Scanner sc = new Scanner(System.in);// 读取窗口数量 nint n = Integer.parseInt(sc.nextLine());// 读取每个窗口的元素数量 kint k = Integer.parseInt(sc.nextLine());// 存储所有列表,每个列表用 LinkedList 存储ArrayList<LinkedList<Integer>> lists = new ArrayList<>();// 循环读取输入,直到输入结束while (sc.hasNextLine()) {String line = sc.nextLine();// 本地测试,以空行作为输入截止条件if (line.length() == 0) break;// 将输入行按空格分割,转换为 Integer 数组Integer[] nums =Arrays.stream(line.split(" ")).map(Integer::parseInt).toArray(Integer[]::new);// 将数组转换为 LinkedList,并存入 listslists.add(new LinkedList<>(Arrays.asList(nums)));}// 创建一个大小为 k * n 的一维数组,用于模拟窗口矩阵int[] windows = new int[k * n];// 当前填充位置的索引int idx = 0;// 当前从第 level 个列表中取值int level = 0;// 当窗口矩阵未填满时,继续填充while (idx < windows.length) {// 标记当前轮次是否发生了“借”动作boolean flag = false;// 从当前列表 lists.get(level) 中取 n 个元素for (int i = 0; i < n; i++) {// 将列表的第一个元素取出,放入 windows 中windows[idx++] = lists.get(level).removeFirst();// 如果当前列表为空且还有其他列表,则从下一个列表中“借”元素if (lists.get(level).size() == 0 && lists.size() > 1) {// 删除当前空列表lists.remove(level);// 防止 level 越界level %= lists.size();// 标记发生了“借”动作flag = true;}}// 如果没有发生“借”动作,则切换到下一个列表if (!flag) {level = (level + 1) % lists.size(); // 防止越界}}// 使用 StringJoiner 拼接结果,元素之间用空格分隔StringJoiner sj = new StringJoiner(" ");// 按列遍历窗口矩阵for (int j = 0; j < n; j++) { // 遍历列号for (int i = 0; i < k; i++) { // 遍历行号// 按列收集元素,拼接成字符串sj.add(windows[i * n + j] + "");}}// 输出结果System.out.println(sj);}
}

代码逻辑详解

1. 输入处理
  • 使用 Scanner 逐行读取输入。
  • 第一行读取窗口数量 n,第二行读取每个窗口的元素数量 k
  • 后续行读取每个列表,并将其转换为 LinkedList<Integer>,存储在 lists 中。
2. 窗口矩阵填充
  • 创建一个大小为 k * n 的一维数组 windows,用于模拟窗口矩阵。
  • 使用指针 idx 记录当前填充的位置。
  • 使用变量 level 记录当前从哪个列表中取值。
3. 填充逻辑
  • 从当前列表 lists.get(level) 中取出 n 个元素,依次填充到 windows 中。
  • 如果当前列表元素不足,则从下一个列表中“借”元素,并删除当前空列表。
  • 更新指针 idxlevel,确保填充过程正确。
4. 输出结果
  • 使用 StringJoiner 按列遍历 windows 矩阵,将元素按窗口顺序拼接成字符串。
  • 最终输出结果。

示例运行

输入
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
解析
  • 从第一个列表中选择 4 条元素 0 1 2 3,分别放到 4 个窗口中。
  • 从第二个列表中选择 4 条元素 10 11 12 13,分别放到 4 个窗口中。
  • 从第三个列表中选择 4 条元素 20 21 22 23,分别放到 4 个窗口中。
  • 再次从第一个列表中选择 4 条元素 4 5 6 7,分别放到 4 个窗口中。
  • 从第一个列表中选择剩下的 2 条元素 8 9,分别放到窗口1和窗口2。
  • 从第二个列表中选择剩下的 2 条元素 18 19,分别放到窗口3和窗口4。

最终输出的元素列表按照窗口顺序排列。


通过以上注释和讲解,你应该能够理解代码的每一部分功能和实现逻辑。如果还有疑问,欢迎随时提问!

四、Python算法源码

以下是 Python 代码的详细注释和讲解,帮助你理解每一部分的功能和实现逻辑:


代码结构

  1. 输入处理

    • 使用 input() 读取输入数据。
    • 解析窗口数量 n 和每个窗口的元素数量 k
    • 读取多个列表,并将每个列表转换为整数列表,存储在 lists 中。
  2. 窗口矩阵填充

    • 创建一个一维列表 windows,用于模拟 kn 列的窗口矩阵。
    • 使用指针 idx 记录当前填充的位置。
    • 使用变量 level 记录当前从哪个列表中取值。
  3. 填充逻辑

    • 从当前列表 lists[level] 中取出 n 个元素,依次填充到 windows 中。
    • 如果当前列表元素不足,则从下一个列表中“借”元素。
    • 更新指针 idxlevel,确保填充过程正确。
  4. 输出结果

    • 按列遍历 windows 矩阵,将元素按窗口顺序收集到 ans 列表中。
    • 最终将 ans 转换为字符串并输出。

代码逐行注释

# 读取窗口数量 n
n = int(input())
# 读取每个窗口的元素数量 k
k = int(input())# 存储所有列表
lists = []
while True:try:# 读取一行输入,并将其转换为整数列表,存入 listslists.append(list(map(int, input().split())))except:# 捕获异常(如输入结束),退出循环break# 算法入口
def getResult():# 创建一个大小为 k * n 的一维列表,用于模拟窗口矩阵windows = [0] * (k * n)# 当前填充位置的索引idx = 0# 当前从第 level 个列表中取值level = 0# 当窗口矩阵未填满时,继续填充while idx < len(windows):# 标记当前轮次是否发生了“借”动作flag = False# 从当前列表 lists[level] 中取 n 个元素for _ in range(n):# 将列表的第一个元素取出,放入 windows 中windows[idx] = lists[level].pop(0)idx += 1# 如果当前列表为空且还有其他列表,则从下一个列表中“借”元素if len(lists[level]) == 0 and len(lists) > 1:# 删除当前空列表lists.pop(level)# 防止 level 越界level %= len(lists)# 标记发生了“借”动作flag = True# 如果没有发生“借”动作,则切换到下一个列表if not flag:level = (level + 1) % len(lists)  # 防止越界# 用于存储最终结果的列表ans = []# 按列遍历窗口矩阵for j in range(n):  # 遍历列号for i in range(k):  # 遍历行号# 按列收集元素,存入 ansans.append(windows[i * n + j])# 将结果列表转换为字符串,元素之间用空格分隔return " ".join(map(str, ans))# 调用算法并输出结果
print(getResult())

代码逻辑详解

1. 输入处理
  • 使用 input() 逐行读取输入。
  • 第一行读取窗口数量 n,第二行读取每个窗口的元素数量 k
  • 后续行读取每个列表,并将其转换为整数列表,存储在 lists 中。
2. 窗口矩阵填充
  • 创建一个大小为 k * n 的一维列表 windows,用于模拟窗口矩阵。
  • 使用指针 idx 记录当前填充的位置。
  • 使用变量 level 记录当前从哪个列表中取值。
3. 填充逻辑
  • 从当前列表 lists[level] 中取出 n 个元素,依次填充到 windows 中。
  • 如果当前列表元素不足,则从下一个列表中“借”元素,并删除当前空列表。
  • 更新指针 idxlevel,确保填充过程正确。
4. 输出结果
  • 按列遍历 windows 矩阵,将元素按窗口顺序收集到 ans 列表中。
  • 最终将 ans 转换为字符串并输出。

示例运行

输入
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
解析
  • 从第一个列表中选择 4 条元素 0 1 2 3,分别放到 4 个窗口中。
  • 从第二个列表中选择 4 条元素 10 11 12 13,分别放到 4 个窗口中。
  • 从第三个列表中选择 4 条元素 20 21 22 23,分别放到 4 个窗口中。
  • 再次从第一个列表中选择 4 条元素 4 5 6 7,分别放到 4 个窗口中。
  • 从第一个列表中选择剩下的 2 条元素 8 9,分别放到窗口1和窗口2。
  • 从第二个列表中选择剩下的 2 条元素 18 19,分别放到窗口3和窗口4。

最终输出的元素列表按照窗口顺序排列。


通过以上注释和讲解,你应该能够理解代码的每一部分功能和实现逻辑。如果还有疑问,欢迎随时提问!

五、C/C++算法源码:

以下是 C 语言和 C++ 代码的详细注释和讲解,帮助你理解每一部分的功能和实现逻辑:


C 语言代码

代码结构

  1. 链表实现

    • 定义链表节点 Node 和链表 Link 结构。
    • 实现链表的创建、尾插、头删等操作。
  2. 输入处理

    • 使用 scanfgets 读取输入数据。
    • 解析窗口数量 n 和每个窗口的元素数量 k
    • 读取多个列表,并将每个列表转换为链表,存储在 lists 数组中。
  3. 窗口矩阵填充

    • 创建一个一维数组 windows,用于模拟 kn 列的窗口矩阵。
    • 使用指针 idx 记录当前填充的位置。
    • 使用变量 level 记录当前从哪个列表中取值。
  4. 填充逻辑

    • 从当前列表 lists[level] 中取出 n 个元素,依次填充到 windows 中。
    • 如果当前列表元素不足,则从下一个列表中“借”元素。
    • 更新指针 idxlevel,确保填充过程正确。
  5. 输出结果

    • 按列遍历 windows 矩阵,将元素按窗口顺序输出。

C 语言代码逐行注释

#include <stdio.h>
#include <string.h>
#include <stdlib.h>#define MAX_ROWS 100       // 最大列表数量
#define MAX_ROW_LEN 10000  // 每行最大长度/* 链表节点 */
typedef struct Node {int val;              // 节点值struct Node *next;    // 下一个节点指针
} Node;/* 链表 */
typedef struct Link {int size;             // 链表大小Node *head;           // 链表头节点Node *tail;           // 链表尾节点
} Link;// 创建链表
Link *new_Link() {Link *link = (Link *) malloc(sizeof(Link));link->size = 0;link->head = NULL;link->tail = NULL;return link;
}// 尾插
void addLast_Link(Link *link, int val) {Node *node = (Node *) malloc(sizeof(Node));node->val = val;node->next = NULL;if (link->size == 0) {link->head = node;link->tail = node;} else {link->tail->next = node;link->tail = node;}link->size++;
}// 头删
int removeFirst_Link(Link *link) {if (link->size == 0) exit(-1);Node *removed = link->head;if (link->size == 1) {link->head = NULL;link->tail = NULL;} else {link->head = link->head->next;}link->size--;int val = removed->val;free(removed);return val;
}int main() {int n, k;scanf("%d %d", &n, &k);  // 读取窗口数量 n 和每个窗口的元素数量 kgetchar();  // 消耗换行符Link *lists[MAX_ROWS];  // 存储所有列表int lists_size = 0;     // 当前列表数量char s[MAX_ROW_LEN];while (gets(s)) {  // 逐行读取输入// 本地测试,以空行作为输入截止条件if (strlen(s) == 0) break;Link *link = new_Link();  // 创建一个新链表// 将输入行按空格分割,转换为链表节点char *token = strtok(s, " ");while (token != NULL) {addLast_Link(link, atoi(token));  // 将节点添加到链表尾部token = strtok(NULL, " ");}lists[lists_size++] = link;  // 将链表存入 lists}// 创建一个大小为 k * n 的一维数组,用于模拟窗口矩阵int windows[k * n];// 当前填充位置的索引int idx = 0;// 当前从第 level 个列表中取值int level = 0;// 当窗口矩阵未填满时,继续填充while (idx < k * n) {// 标记当前轮次是否发生了“借”动作int flag = 0;// 从当前列表 lists[level] 中取 n 个元素for (int i = 0; i < n; i++) {windows[idx++] = removeFirst_Link(lists[level]);  // 取出元素并填充到 windows// 如果当前列表为空且还有其他列表,则从下一个列表中“借”元素if (lists[level]->size == 0 && lists_size > 1) {// 删除第 level 个空列表for (int j = level + 1; j < lists_size; j++) {lists[j - 1] = lists[j];}lists_size--;level %= lists_size;  // 防止越界flag = 1;  // 标记发生了“借”动作}}// 如果没有发生“借”动作,则切换到下一个列表if (!flag) {level = (level + 1) % lists_size;  // 防止越界}}// 按列遍历窗口矩阵for (int j = 0; j < n; j++) {  // 遍历列号for (int i = 0; i < k; i++) {  // 遍历行号// 按列打印元素printf("%d", windows[i * n + j]);if (j != n - 1 || i != k - 1) {printf(" ");}}}return 0;
}

C++ 代码

代码结构

  1. 输入处理

    • 使用 cin 读取输入数据。
    • 解析窗口数量 n 和每个窗口的元素数量 k
    • 读取多个列表,并将每个列表存储在 vector<deque<int>> 中。
  2. 窗口矩阵填充

    • 创建一个一维数组 windows,用于模拟 kn 列的窗口矩阵。
    • 使用指针 idx 记录当前填充的位置。
    • 使用变量 level 记录当前从哪个列表中取值。
  3. 填充逻辑

    • 从当前列表 lists[level] 中取出 n 个元素,依次填充到 windows 中。
    • 如果当前列表元素不足,则从下一个列表中“借”元素。
    • 更新指针 idxlevel,确保填充过程正确。
  4. 输出结果

    • 按列遍历 windows 矩阵,将元素按窗口顺序输出。

C++ 代码逐行注释

#include <iostream>
#include <vector>
#include <deque>
#include <sstream>
using namespace std;int main() {int n, k;cin >> n >> k;  // 读取窗口数量 n 和每个窗口的元素数量 kcin.ignore();   // 忽略换行符vector<deque<int>> lists;  // 存储所有列表string s;while (getline(cin, s)) {  // 逐行读取输入if (s.empty()) break;  // 本地测试,以空行作为输入截止条件deque<int> list;  // 创建一个新列表stringstream ss(s);int num;while (ss >> num) {  // 将输入行按空格分割,转换为整数list.push_back(num);  // 将元素添加到列表尾部}lists.push_back(list);  // 将列表存入 lists}// 创建一个大小为 k * n 的一维数组,用于模拟窗口矩阵vector<int> windows(k * n);// 当前填充位置的索引int idx = 0;// 当前从第 level 个列表中取值int level = 0;// 当窗口矩阵未填满时,继续填充while (idx < k * n) {// 标记当前轮次是否发生了“借”动作bool flag = false;// 从当前列表 lists[level] 中取 n 个元素for (int i = 0; i < n; i++) {windows[idx++] = lists[level].front();  // 取出元素并填充到 windowslists[level].pop_front();  // 删除已取出的元素// 如果当前列表为空且还有其他列表,则从下一个列表中“借”元素if (lists[level].empty() && lists.size() > 1) {lists.erase(lists.begin() + level);  // 删除第 level 个空列表level %= lists.size();  // 防止越界flag = true;  // 标记发生了“借”动作}}// 如果没有发生“借”动作,则切换到下一个列表if (!flag) {level = (level + 1) % lists.size();  // 防止越界}}// 按列遍历窗口矩阵for (int j = 0; j < n; j++) {  // 遍历列号for (int i = 0; i < k; i++) {  // 遍历行号// 按列打印元素cout << windows[i * n + j];if (j != n - 1 || i != k - 1) {cout << " ";}}}return 0;
}

总结

  • C 语言代码:使用链表和数组实现,适合对内存管理有较高要求的场景。
  • C++ 代码:使用 vectordeque 实现,代码更简洁,适合快速开发。

两种代码的逻辑完全一致,只是实现方式不同。如果你有更多问题,欢迎随时提问!

六、尾言

什么是华为OD?

华为OD(Outsourcing Developer,外包开发工程师)是华为针对软件开发工程师岗位的一种招聘形式,主要包括笔试、技术面试以及综合面试等环节。尤其在笔试部分,算法题的机试至关重要。

为什么刷题很重要?

  1. 机试是进入技术面的第一关:
    华为OD机试(常被称为机考)主要考察算法和编程能力。只有通过机试,才能进入后续的技术面试环节。

  2. 技术面试需要手撕代码:
    技术一面和二面通常会涉及现场编写代码或算法题。面试官会注重考察候选人的思路清晰度、代码规范性以及解决问题的能力。因此提前刷题、多练习是通过面试的重要保障。

  3. 入职后的可信考试:
    入职华为后,还需要通过“可信考试”。可信考试分为三个等级:

    • 入门级:主要考察基础算法与编程能力。
    • 工作级:更贴近实际业务需求,可能涉及复杂的算法或与工作内容相关的场景题目。
    • 专业级:最高等级,考察深层次的算法以及优化能力,与薪资直接挂钩。

刷题策略与说明:

2024年8月14日之后,华为OD机试的题库转为 E卷,由往年题库(D卷、A卷、B卷、C卷)和全新题目组成。刷题时可以参考以下策略:

  1. 关注历年真题:

    • 题库中的旧题占比较大,建议优先刷历年的A卷、B卷、C卷、D卷题目。
    • 对于每道题目,建议深度理解其解题思路、代码实现,以及相关算法的适用场景。
  2. 适应新题目:

    • E卷中包含全新题目,需要掌握全面的算法知识和一定的灵活应对能力。
    • 建议关注新的刷题平台或交流群,获取最新题目的解析和动态。
  3. 掌握常见算法:
    华为OD考试通常涉及以下算法和数据结构:

    • 排序算法(快速排序、归并排序等)
    • 动态规划(背包问题、最长公共子序列等)
    • 贪心算法
    • 栈、队列、链表的操作
    • 图论(最短路径、最小生成树等)
    • 滑动窗口、双指针算法
  4. 保持编程规范:

    • 注重代码的可读性和注释的清晰度。
    • 熟练使用常见编程语言,如C++、Java、Python等。

如何获取资源?

  1. 官方参考:

    • 华为招聘官网或相关的招聘平台会有一些参考信息。
    • 华为OD的相关公众号可能也会发布相关的刷题资料或学习资源。
  2. 加入刷题社区:

    • 找到可信的刷题交流群,与其他备考的小伙伴交流经验。
    • 关注知名的刷题网站,如LeetCode、牛客网等,这些平台上有许多华为OD的历年真题和解析。
  3. 寻找系统性的教程:

    • 学习一本经典的算法书籍,例如《算法导论》《剑指Offer》《编程之美》等。
    • 完成系统的学习课程,例如数据结构与算法的在线课程。

积极心态与持续努力:

刷题的过程可能会比较枯燥,但它能够显著提升编程能力和算法思维。无论是为了通过华为OD的招聘考试,还是为了未来的职业发展,这些积累都会成为重要的财富。

考试注意细节

  1. 本地编写代码

    • 在本地 IDE(如 VS Code、PyCharm 等)上编写、保存和调试代码,确保逻辑正确后再复制粘贴到考试页面。这样可以减少语法错误,提高代码准确性。
  2. 调整心态,保持冷静

    • 遇到提示不足或实现不确定的问题时,不必慌张,可以采用更简单或更有把握的方法替代,确保思路清晰。
  3. 输入输出完整性

    • 注意训练和考试时都需要编写完整的输入输出代码,尤其是和题目示例保持一致。完成代码后务必及时调试,确保功能符合要求。
  4. 快捷键使用

    • 删除行可用 Ctrl+D,复制、粘贴和撤销分别为 Ctrl+CCtrl+VCtrl+Z,这些可以正常使用。
    • 避免使用 Ctrl+S,以免触发浏览器的保存功能。
  5. 浏览器要求

    • 使用最新版的 Google Chrome 浏览器完成考试,确保摄像头开启并正常工作。考试期间不要切换到其他网站,以免影响考试成绩。
  6. 交卷相关

    • 答题前,务必仔细查看题目示例,避免遗漏要求。
    • 每完成一道题后,点击【保存并调试】按钮,多次保存和调试是允许的,系统会记录得分最高的一次结果。完成所有题目后,点击【提交本题型】按钮。
    • 确保在考试结束前提交试卷,避免因未保存或调试失误而丢分。
  7. 时间和分数安排

    • 总时间:150 分钟;总分:400 分。
    • 试卷结构:2 道一星难度题(每题 100 分),1 道二星难度题(200 分)。及格分为 150 分。合理分配时间,优先完成自己擅长的题目。
  8. 考试环境准备

    • 考试前请备好草稿纸和笔。考试中尽量避免离开座位,确保监控画面正常。
    • 如需上厕所,请提前规划好时间以减少中途离开监控的可能性。
  9. 技术问题处理

    • 如果考试中遇到断电、断网、死机等技术问题,可以关闭浏览器并重新打开试卷链接继续作答。
    • 出现其他问题,请第一时间联系 HR 或监考人员进行反馈。

祝你考试顺利,取得理想成绩!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/68399.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C# 提取PDF表单数据

目录 使用工具 C# 提取多个PDF表单域的数据 C# 提取特定PDF表单域的数据 PDF表单是一种常见的数据收集工具&#xff0c;广泛应用于调查问卷、业务合同等场景。凭借出色的跨平台兼容性和标准化特点&#xff0c;PDF表单在各行各业中得到了广泛应用。然而&#xff0c;当需要整合…

http://noi.openjudge.cn/——4.2算法之数论——2419:Coins

题目 总时间限制: 1000ms 内存限制: 131072kB 描述 Snoopy has three coins. One day he tossed them on a table then and tried to flip some of them so that they had either all heads or all tails facing up. After several attempts, he found that regardless of the…

损失函数 Loss Function

分类问题和回归问题常使用的损失函数如下&#xff1a; 分类问题 交叉熵损失函数&#xff08;Cross-Entropy Loss&#xff09;&#xff1a;用于衡量两个概率分布之间的差异&#xff0c;在多分类问题中广泛应用。 ce_loss nn.CrossEntropyLoss() 回归问题 均方误差损失函数&…

3.日常英语笔记

screening discrepancies 筛选差异 The team found some screening discrepancies in the data. 团队在数据筛选中发现了些差异。 Don’t tug at it ,or it will fall over and crush you. tug 拉&#xff0c;拽&#xff0c;拖 He tugged the door open with all his might…

解析“in the wild”——编程和生活中的俚语妙用

解析“in the wild”——编程和生活中的俚语妙用 看下面的技术文章中遇到 in the wild这个词&#xff0c;想要研究一下&#xff0c;遂产生此文。 Are there ever pointers to pointers to pointers? There is an old programming joke which says you can rate C programmers…

软件测试丨从自动化软件测试到自主测试,还差几步?

在当今万物互联、信息爆炸的时代&#xff0c;软件测试的角色显得越发重要。作为软件开发生命周期&#xff08;SDLC&#xff09;中的关键环节&#xff0c;测试不仅仅是保障软件质量的工具&#xff0c;更是推动产品迭代的助推器。随着自动化测试技术的崛起&#xff0c;测试开发变…

高阶C语言|深入理解字符串函数和内存函数

文章目录 前言1.求字符串长度1.1 字符串长度函数&#xff1a;strlen模拟实现 长度不受限制的字符串函数1.2 字符串拷贝函数&#xff1a;strcpy模拟实现 1.3 字符串连接函数&#xff1a;strcat模拟实现 1.4 字符串比较函数&#xff1a;strcmp模拟实现 长度受限制的字符串函数2.1…

Golang Ticker Reset异常的坑

前言 延迟执行的场景我们通常会使用time.NewTimer(…)来实现&#xff0c;当一些场合可能需要使用timer.Reset(…)方法修改超时时间&#xff0c;这时使用要多注意&#xff0c; 使用不当会导致Reset失败&#xff0c;或是重复执行两次的情况。 复现 下面这段代码我们是希望&…

Chameleon(变色龙) 跨平台编译C文件,并一次性生成多个平台的可执行文件

地址:https://github.com/MartinxMax/Chameleon Chameleon 跨平台编译C文件&#xff0c;并一次性生成多个平台的可执行文件。可以通过编译Chameleon自带的.C文件反向Shell生成不同平台攻击载荷。 登录 & 代理设置 按照以下步骤设置 Docker 的代理&#xff1a; 创建配置目…

DFFormer实战:使用DFFormer实现图像分类任务(二)

文章目录 训练部分导入项目使用的库设置随机因子设置全局参数图像预处理与增强读取数据设置Loss设置模型设置优化器和学习率调整策略设置混合精度&#xff0c;DP多卡&#xff0c;EMA定义训练和验证函数训练函数验证函数调用训练和验证方法 运行以及结果查看测试完整的代码 在上…

几种K8s运维管理平台对比说明

目录 深入体验**结论**对比分析表格**1. 功能对比****2. 用户界面****3. 多租户支持****4. DevOps支持** 细对比分析1. **Kuboard**2. **xkube**3. **KubeSphere**4. **Dashboard****对比总结** 深入体验 KuboardxkubeKubeSphereDashboard 结论 如果您需要一个功能全面且适合…

DeepSeek API 的获取与对话示例

代码文件下载&#xff1a;Code 在线链接&#xff1a;Kaggle | Colab 文章目录 注册并获取API环境依赖设置 API单轮对话多轮对话流式输出更换模型 注册并获取API 访问 https://platform.deepseek.com/sign_in 进行注册并登录&#xff1a; 新用户注册后将赠送 10 块钱余额&#…

Vue 3 + TypeScript 实现父子组件协同工作案例解析

引言 在现代的前端开发中&#xff0c;Vue.js 作为一款流行的渐进式 JavaScript 框架&#xff0c;为我们构建交互式用户界面提供了强大的支持。Vue 3 的推出带来了许多新特性&#xff0c;尤其是组合式 API 的引入&#xff0c;让代码的组织和复用更加灵活。同时&#xff0c;TypeS…

基于STM32的循迹小车设计与实现

1 系统方案设计 根据系统设计功能&#xff0c;展开基于STM32的循迹小车设计&#xff0c;整体设计框图如图2.1所示。系统采用STM32单片机作为控制器,通过L298驱动器控制两个直流电机实现对小车的运动控制&#xff0c;两路红外模块实现黑线的检测&#xff0c;HC-SR04超声波模块实…

14.模型,纹理,着色器

模型、纹理和着色器是计算机图形学中的三个核心概念&#xff0c;用通俗易懂的方式来解释&#xff1a; 1. 模型&#xff1a;3D物体的骨架 通俗解释&#xff1a; 模型就像3D物体的骨架&#xff0c;定义了物体的形状和结构。 比如&#xff0c;一个房子的模型包括墙、屋顶、窗户等…

Docker/K8S

文章目录 项目地址一、Docker1.1 创建一个Node服务image1.2 volume1.3 网络1.4 docker compose 二、K8S2.1 集群组成2.2 Pod1. 如何使用Pod(1) 运行一个pod(2) 运行多个pod 项目地址 教程作者&#xff1a;教程地址&#xff1a; https://www.bilibili.com/video/BV1Zn4y1X7AZ?…

Ubuntu 20.04安装Protocol Buffers 2.5.0

个人博客地址&#xff1a;Ubuntu 20.04安装Protocol Buffers 2.5.0 | 一张假钞的真实世界 安装过程 Protocol Buffers 2.5.0源码下载&#xff1a;https://github.com/protocolbuffers/protobuf/tree/v2.5.0。下载并解压。 将autogen.sh文件中以下内容&#xff1a; curl htt…

算法每日双题精讲 —— 二分查找(寻找旋转排序数组中的最小值,点名)

&#x1f31f;快来参与讨论&#x1f4ac;&#xff0c;点赞&#x1f44d;、收藏⭐、分享&#x1f4e4;&#xff0c;共创活力社区。 &#x1f31f; 别再犹豫了&#xff01;快来订阅我们的算法每日双题精讲专栏&#xff0c;一起踏上算法学习的精彩之旅吧&#x1f4aa; 在算法的…

【踩坑日常,已解决】彻底修改IDEA项目的JDK版本,8改为17

三处修改彻底解决IDEA中JDK版本不对问题&#xff08;8改为17&#xff09; 文章目录 三处修改彻底解决IDEA中JDK版本不对问题&#xff08;8改为17&#xff09;第一处第二处第三处 第一处 setting -> Build, Execution, Deployment -> Java Compiler -> Target bytecod…

linux naive代理设置

naive linux客户端 Release v132.0.6834.79-2 klzgrad/naiveproxy GitHub Client setup Run ./naive with the following config.json to get a SOCKS5 proxy at local port 1080. {"listen": "socks://127.0.0.1:1080","proxy": "htt…