Bootstrap

【2024年华为OD机试】(A卷,200分)- 无向图染色 (JavaScript&Java & Python&C/C++)

在这里插入图片描述

一、问题描述

题目描述

给定一个无向图,要求对图中的节点进行染色,颜色可以选择红色或黑色。要求相邻的两个节点不能同时为红色。求有多少种不同的染色方案。

输入描述

  • 第一行输入两个整数 MN,分别表示图中的节点数和边数。
  • 接下来的 N 行,每行输入两个整数 V1V2,表示图中的一条边。

输出描述

  • 输出一个整数,表示满足条件的染色方案数。

数据范围

  • 1 <= M <= 15
  • 0 <= N <= M * 3
  • 图中节点不一定全部连通。

解题思路

1. 问题分析

本题要求对无向图的节点进行染色,且相邻节点不能同时为红色。由于节点数最多为15,可以考虑使用回溯法或暴力枚举的方法来求解。

2. 染色方案的计算

对于每个节点,可以选择染红色或黑色。但由于相邻节点不能同时为红色,因此在选择染红色的节点时,必须确保其相邻节点没有被染成红色。

3. 连通分量的处理

由于图中可能存在多个连通分量,每个连通分量的染色方案是独立的。因此,可以先求出每个连通分量的染色方案数,然后将所有连通分量的染色方案数相乘,得到总的染色方案数。

4. 回溯法实现

  • 使用回溯法枚举所有可能的染色方案。
  • 对于每个节点,尝试将其染成红色或黑色。
  • 如果选择染红色,则需要检查其相邻节点是否已经被染成红色。如果相邻节点中有红色节点,则不能选择染红色。
  • 递归处理下一个节点,直到所有节点都被处理完毕。

5. 边界情况处理

  • 如果图中没有边,即所有节点都是孤立的,那么每个节点都可以独立选择染红色或黑色,总的染色方案数为 2^M
  • 如果图中有多个连通分量,需要分别计算每个连通分量的染色方案数,然后相乘得到总的染色方案数。

示例分析

示例1

输入:

4 4
1 2
2 4
3 4
1 3

输出:

7

解释:

  • 节点1、2、3、4相互连接,形成一个连通分量。
  • 染色方案数为7。

示例2

输入:

3 3
1 2
1 3
2 3

输出:

4

解释:

  • 节点1、2、3相互连接,形成一个连通分量。
  • 染色方案数为4。

示例3

输入:

4 3
1 2
2 3
3 4

输出:

8

解释:

  • 节点1、2、3、4形成一个连通分量。
  • 染色方案数为8。

示例4

输入:

4 3
1 2
1 3
2 3

输出:

8

解释:

  • 节点1、2、3形成一个连通分量,节点4是孤立的。
  • 节点1、2、3的染色方案数为4,节点4的染色方案数为2。
  • 总的染色方案数为4 * 2 = 8。

总结

本题的关键在于如何处理图中的连通分量以及如何通过回溯法枚举所有可能的染色方案。由于节点数较少,回溯法可以在合理的时间内求解。

二、JavaScript算法源码

代码解析

这段代码通过暴力枚举的方式求解无向图的染色方案数。以下是代码的详细解析:


1. 输入处理

  • 使用 readline 模块读取输入。
  • 第一行输入 MN,分别表示节点数和边数。
  • 后续 N 行输入每条边的信息,存储在数组 arr 中。

2. 构建邻接表

  • 使用 connect 对象存储每个节点的相邻节点。
  • 遍历所有边,将相邻节点信息存入 connect 中。例如,connect[v1] 存储与节点 v1 相邻的所有节点。

3. 染色方案计算

  • 初始化 count 为 1,表示全黑的染色方案。
  • 使用深度优先搜索(DFS)枚举所有可能的染红节点组合。
    • 对于每个节点,尝试将其染成红色。
    • 如果新加入的节点与已染红的节点相邻,则跳过(剪枝)。
    • 如果新加入的节点可以染成红色,则更新 count,并继续递归枚举。

4. DFS 实现

  • dfs(m, index, path) 是递归函数,用于枚举染红节点的组合。
    • m:节点总数。
    • index:当前枚举的起始节点。
    • path:存储当前已染红节点的相邻节点集合。
  • 在递归过程中:
    • 如果 path.length === m,表示所有节点都已处理,直接返回。
    • 遍历从 indexm 的所有节点,尝试将其染成红色。
    • 如果新加入的节点与已染红节点相邻,则跳过(剪枝)。
    • 否则,更新 count,并将新加入节点的相邻节点加入 path,继续递归。

5. 边界处理

  • 如果某个节点没有相邻节点(即 connect[i]undefined),则直接跳过相邻节点检查。
  • 递归结束后,返回 count,即所有合法的染色方案数。

6. 性能分析

  • 优点:实现简单,直接利用节点间的相邻关系进行枚举。
  • 缺点:性能较差,尤其是在节点数较多时(如 M = 15),时间复杂度为 O(2^M),可能导致运行时间较长。

7. 优化建议

  • 基于连通分量的优化
    • 使用并查集(Union-Find)将图划分为多个连通分量。
    • 对每个连通分量分别计算染色方案数,最后将所有连通分量的方案数相乘。
    • 这种方法可以显著减少枚举的次数,提高性能。

8. 代码示例优化

以下是基于连通分量优化的伪代码:

function getResult(arr, m) {
  // 1. 使用并查集划分连通分量
  const uf = new UnionFind(m);
  for (let [v1, v2] of arr) {
    uf.union(v1, v2);
  }

  // 2. 统计每个连通分量的节点
  const components = {};
  for (let i = 1; i <= m; i++) {
    const root = uf.find(i);
    components[root] ? components[root].push(i) : (components[root] = [i]);
  }

  // 3. 计算每个连通分量的染色方案数
  let result = 1;
  for (const root in components) {
    const nodes = components[root];
    const count = calculateComponent(nodes, arr);
    result *= count;
  }

  return result;
}

function calculateComponent(nodes, arr) {
  // 计算单个连通分量的染色方案数
  // 使用 DFS 或回溯法
}

9. 总结

  • 当前代码通过暴力枚举实现,适合节点数较少的情况(如 M <= 15)。
  • 对于更大规模的图,建议使用基于连通分量的优化方法,以提高性能。

三、Java算法源码

代码解析

这段 Java 代码通过暴力枚举的方式求解无向图的染色方案数。以下是代码的详细解析:


1. 输入处理

  • 使用 Scanner 读取输入。
  • 第一行输入 MN,分别表示节点数和边数。
  • 后续 N 行输入每条边的信息,存储在二维数组 edges 中。

2. 构建邻接表

  • 使用 HashMap<Integer, HashSet<Integer>> 存储每个节点的相邻节点。
  • 遍历所有边,将相邻节点信息存入 connect 中。例如,connect.get(v1) 存储与节点 v1 相邻的所有节点。

3. 染色方案计算

  • 初始化 count 为 1,表示全黑的染色方案。
  • 调用 dfs 方法,递归枚举所有可能的染红节点组合。

4. DFS 实现

  • dfs 方法是递归函数,用于枚举染红节点的组合。
    • connect:邻接表,存储每个节点的相邻节点。
    • m:节点总数。
    • index:当前枚举的起始节点。
    • count:当前合法的染色方案数。
    • path:存储当前已染红节点的相邻节点集合。
  • 在递归过程中:
    • 如果 path.size() == m,表示所有节点都已处理,直接返回 count
    • 遍历从 indexm 的所有节点,尝试将其染成红色。
    • 如果新加入的节点与已染红节点相邻,则跳过(剪枝)。
    • 否则,更新 count,并将新加入节点的相邻节点加入 path,继续递归。

5. 边界处理

  • 如果某个节点没有相邻节点(即 connect 中不存在该节点),则直接跳过相邻节点检查。
  • 递归结束后,返回 count,即所有合法的染色方案数。

6. 性能分析

  • 优点:实现简单,直接利用节点间的相邻关系进行枚举。
  • 缺点:性能较差,尤其是在节点数较多时(如 M = 15),时间复杂度为 O(2^M),可能导致运行时间较长。

7. 优化建议

  • 基于连通分量的优化
    • 使用并查集(Union-Find)将图划分为多个连通分量。
    • 对每个连通分量分别计算染色方案数,最后将所有连通分量的方案数相乘。
    • 这种方法可以显著减少枚举的次数,提高性能。

8. 代码示例优化

以下是基于连通分量优化的伪代码:

public static int getResult(int[][] edges, int m) {
    // 1. 使用并查集划分连通分量
    UnionFind uf = new UnionFind(m);
    for (int[] edge : edges) {
        uf.union(edge[0], edge[1]);
    }

    // 2. 统计每个连通分量的节点
    HashMap<Integer, List<Integer>> components = new HashMap<>();
    for (int i = 1; i <= m; i++) {
        int root = uf.find(i);
        components.putIfAbsent(root, new ArrayList<>());
        components.get(root).add(i);
    }

    // 3. 计算每个连通分量的染色方案数
    int result = 1;
    for (List<Integer> nodes : components.values()) {
        int count = calculateComponent(nodes, edges);
        result *= count;
    }

    return result;
}

public static int calculateComponent(List<Integer> nodes, int[][] edges) {
    // 计算单个连通分量的染色方案数
    // 使用 DFS 或回溯法
}

9. 总结

  • 当前代码通过暴力枚举实现,适合节点数较少的情况(如 M <= 15)。
  • 对于更大规模的图,建议使用基于连通分量的优化方法,以提高性能。

10. 完整代码(优化前)

以下是当前实现的完整代码:

import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        int m = sc.nextInt();
        int n = sc.nextInt();

        int[][] edges = new int[n][2];
        for (int i = 0; i < n; i++) {
            edges[i][0] = sc.nextInt();
            edges[i][1] = sc.nextInt();
        }

        System.out.println(getResult(edges, m));
    }

    public static int getResult(int[][] edges, int m) {
        // connect用于存放每个节点的相邻节点
        HashMap<Integer, HashSet<Integer>> connect = new HashMap<>();

        for (int[] edge : edges) {
            connect.putIfAbsent(edge[0], new HashSet<>());
            connect.get(edge[0]).add(edge[1]);

            connect.putIfAbsent(edge[1], new HashSet<>());
            connect.get(edge[1]).add(edge[0]);
        }

        // 节点从index=1开始,必有count=1个的全黑染色方案
        return dfs(connect, m, 1, 1, new LinkedList<>());
    }

    public static int dfs(
            HashMap<Integer, HashSet<Integer>> connect,
            int m,
            int index,
            int count,
            LinkedList<HashSet<Integer>> path) {
        if (path.size() == m) return count;

        outer:
        for (int i = index; i <= m; i++) {
            // 如果新加入节点i和已有节点j相邻,则说明新加入节点不能染成红色,需要进行剪枝
            for (HashSet<Integer> p : path) {
                if (p.contains(i)) continue outer;
            }

            count++;

            if (connect.containsKey(i)) {
                path.addLast(connect.get(i));
                count = dfs(connect, m, i + 1, count, path);
                path.removeLast();
            } else {
                count = dfs(connect, m, i + 1, count, path);
            }
        }

        return count;
    }
}

11. 运行示例

输入:
4 4
1 2
2 4
3 4
1 3
输出:
7
解释:
  • 节点1、2、3、4相互连接,形成一个连通分量。
  • 染色方案数为7。

四、Python算法源码

代码解析

这段 Python 代码通过暴力枚举的方式求解无向图的染色方案数。以下是代码的详细解析:


1. 输入处理

  • 使用 input() 读取输入。
  • 第一行输入 MN,分别表示节点数和边数。
  • 后续 N 行输入每条边的信息,存储在列表 arr 中。

2. 构建邻接表

  • 使用字典 connect 存储每个节点的相邻节点。
  • 遍历所有边,将相邻节点信息存入 connect 中。例如,connect[v1] 存储与节点 v1 相邻的所有节点。

3. 染色方案计算

  • 初始化 count 为 1,表示全黑的染色方案。
  • 调用 dfs 方法,递归枚举所有可能的染红节点组合。

4. DFS 实现

  • dfs 方法是递归函数,用于枚举染红节点的组合。
    • m:节点总数。
    • index:当前枚举的起始节点。
    • path:存储当前已染红节点的相邻节点集合。
    • count:当前合法的染色方案数。
    • connect:邻接表,存储每个节点的相邻节点。
  • 在递归过程中:
    • 如果 len(path) == m,表示所有节点都已处理,直接返回 count
    • 遍历从 indexm 的所有节点,尝试将其染成红色。
    • 如果新加入的节点与已染红节点相邻,则跳过(剪枝)。
    • 否则,更新 count,并将新加入节点的相邻节点加入 path,继续递归。

5. 边界处理

  • 如果某个节点没有相邻节点(即 connect.get(i)None),则直接跳过相邻节点检查。
  • 递归结束后,返回 count,即所有合法的染色方案数。

6. 性能分析

  • 优点:实现简单,直接利用节点间的相邻关系进行枚举。
  • 缺点:性能较差,尤其是在节点数较多时(如 M = 15),时间复杂度为 O(2^M),可能导致运行时间较长。

7. 优化建议

  • 基于连通分量的优化
    • 使用并查集(Union-Find)将图划分为多个连通分量。
    • 对每个连通分量分别计算染色方案数,最后将所有连通分量的方案数相乘。
    • 这种方法可以显著减少枚举的次数,提高性能。

8. 代码示例优化

以下是基于连通分量优化的伪代码:

def getResult(arr, m):
    # 1. 使用并查集划分连通分量
    uf = UnionFind(m)
    for v1, v2 in arr:
        uf.union(v1, v2)

    # 2. 统计每个连通分量的节点
    components = {}
    for i in range(1, m + 1):
        root = uf.find(i)
        if root not in components:
            components[root] = []
        components[root].append(i)

    # 3. 计算每个连通分量的染色方案数
    result = 1
    for nodes in components.values():
        count = calculateComponent(nodes, arr)
        result *= count

    return result

def calculateComponent(nodes, arr):
    # 计算单个连通分量的染色方案数
    # 使用 DFS 或回溯法

9. 总结

  • 当前代码通过暴力枚举实现,适合节点数较少的情况(如 M <= 15)。
  • 对于更大规模的图,建议使用基于连通分量的优化方法,以提高性能。

10. 完整代码(优化前)

以下是当前实现的完整代码:

# 输入获取
m, n = map(int, input().split())
arr = [list(map(int, input().split())) for i in range(n)]


# 算法入口
def getResult(arr, m):
    """
    :param arr: 边,即[v1, v2]
    :param m: 点数量
    :return: 染色方案数
    """

    # connect用于存放每个节点的相邻节点
    connect = {}

    for v1, v2 in arr:
        if connect.get(v1) is None:
            connect[v1] = set()
        connect[v1].add(v2)

        if connect.get(v2) is None:
            connect[v2] = set()
        connect[v2].add(v1)

    # 节点从1开始
    return dfs(m, 1, [], 1, connect)


# 求解染红节点的全组合情况
def dfs(m, index, path, count, connect):
    """
    :param m: 点数量,点从1计数
    :param index: 当前第几个点
    :param path: 保存点的容器
    :param count: 染色方案数量
    :param connect: 每个节点的相邻节点
    :return: 染色方案数量
    """
    if len(path) == m:
        return count

    flag = False

    for i in range(index, m + 1):
        #  如果新加入节点和已有节点相邻,则说明新加入节点不能染成红色,需要进行剪枝
        for p in path:
            if i in p:
                flag = True
                break

        if flag:
            flag = False
            continue

        count += 1

        if connect.get(i) is not None:
            path.append(connect.get(i))
            count = dfs(m, i + 1, path, count, connect)
            path.pop()
        else:
            count = dfs(m, i + 1, path, count, connect)

    return count


# 算法调用
print(getResult(arr, m))

11. 运行示例

输入:
4 4
1 2
2 4
3 4
1 3
输出:
7
解释:
  • 节点1、2、3、4相互连接,形成一个连通分量。
  • 染色方案数为7。

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

以下是 C++C语言 版本的代码实现,附带详细的中文注释和讲解。


C++ 版本

代码实现

#include <iostream>
#include <vector>
#include <unordered_map>
#include <unordered_set>
using namespace std;

// 深度优先搜索(DFS)函数
int dfs(int m, int index, vector<unordered_set<int>>& path, int count, unordered_map<int, unordered_set<int>>& connect) {
    // 如果所有节点都已处理,返回当前染色方案数
    if (path.size() == m) {
        return count;
    }

    bool flag = false;

    // 遍历从 index 到 m 的所有节点
    for (int i = index; i <= m; i++) {
        // 检查新加入的节点是否与已染红节点相邻
        for (const auto& p : path) {
            if (p.find(i) != p.end()) {
                flag = true;
                break;
            }
        }

        // 如果相邻,跳过当前节点
        if (flag) {
            flag = false;
            continue;
        }

        // 更新染色方案数
        count++;

        // 如果当前节点有相邻节点,加入 path 并递归
        if (connect.find(i) != connect.end()) {
            path.push_back(connect[i]);
            count = dfs(m, i + 1, path, count, connect);
            path.pop_back();
        } else {
            // 如果当前节点没有相邻节点,直接递归
            count = dfs(m, i + 1, path, count, connect);
        }
    }

    return count;
}

// 主算法函数
int getResult(vector<vector<int>>& arr, int m) {
    // 使用哈希表存储每个节点的相邻节点
    unordered_map<int, unordered_set<int>> connect;

    // 构建邻接表
    for (const auto& edge : arr) {
        int v1 = edge[0], v2 = edge[1];
        connect[v1].insert(v2);
        connect[v2].insert(v1);
    }

    // 初始化 path 和 count,调用 DFS 函数
    vector<unordered_set<int>> path;
    return dfs(m, 1, path, 1, connect);
}

int main() {
    int m, n;
    cin >> m >> n;

    vector<vector<int>> arr(n, vector<int>(2));
    for (int i = 0; i < n; i++) {
        cin >> arr[i][0] >> arr[i][1];
    }

    cout << getResult(arr, m) << endl;
    return 0;
}

代码讲解

  1. 输入处理

    • 使用 cin 读取节点数 m 和边数 n
    • 使用二维数组 arr 存储所有边的信息。
  2. 邻接表构建

    • 使用 unordered_map<int, unordered_set<int>> 存储每个节点的相邻节点。
    • 遍历所有边,将相邻节点信息存入 connect 中。
  3. DFS 实现

    • dfs 函数用于枚举所有可能的染红节点组合。
    • 通过 path 存储已染红节点的相邻节点集合。
    • 如果新加入的节点与已染红节点相邻,则跳过(剪枝)。
    • 否则,更新染色方案数,并递归处理下一个节点。
  4. 边界处理

    • 如果某个节点没有相邻节点,则直接跳过相邻节点检查。
    • 递归结束后,返回染色方案数。
  5. 性能分析

    • 时间复杂度:O(2^m),适合 m <= 15 的情况。
    • 空间复杂度:O(m + n),用于存储邻接表和递归栈。

C 语言版本

代码实现

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

#define MAX_NODES 16

// 定义邻接表节点
typedef struct Node {
    int val;
    struct Node* next;
} Node;

// 定义图结构
typedef struct Graph {
    Node* adjList[MAX_NODES];
} Graph;

// 创建新节点
Node* createNode(int val) {
    Node* newNode = (Node*)malloc(sizeof(Node));
    newNode->val = val;
    newNode->next = NULL;
    return newNode;
}

// 添加边到图中
void addEdge(Graph* graph, int v1, int v2) {
    Node* newNode = createNode(v2);
    newNode->next = graph->adjList[v1];
    graph->adjList[v1] = newNode;

    newNode = createNode(v1);
    newNode->next = graph->adjList[v2];
    graph->adjList[v2] = newNode;
}

// 深度优先搜索(DFS)函数
int dfs(int m, int index, bool* isRed, int count, Graph* graph) {
    // 如果所有节点都已处理,返回当前染色方案数
    if (index > m) {
        return count;
    }

    // 检查当前节点是否可以染成红色
    bool canRed = true;
    for (Node* neighbor = graph->adjList[index]; neighbor != NULL; neighbor = neighbor->next) {
        if (isRed[neighbor->val]) {
            canRed = false;
            break;
        }
    }

    // 如果当前节点可以染成红色,尝试染红
    if (canRed) {
        isRed[index] = true;
        count = dfs(m, index + 1, isRed, count + 1, graph);
        isRed[index] = false;
    }

    // 尝试不染红当前节点
    count = dfs(m, index + 1, isRed, count, graph);

    return count;
}

// 主算法函数
int getResult(int edges[][2], int m, int n) {
    // 初始化图
    Graph* graph = (Graph*)malloc(sizeof(Graph));
    for (int i = 0; i < MAX_NODES; i++) {
        graph->adjList[i] = NULL;
    }

    // 构建邻接表
    for (int i = 0; i < n; i++) {
        addEdge(graph, edges[i][0], edges[i][1]);
    }

    // 初始化 isRed 数组
    bool isRed[MAX_NODES] = {false};

    // 调用 DFS 函数
    return dfs(m, 1, isRed, 1, graph);
}

int main() {
    int m, n;
    scanf("%d %d", &m, &n);

    int edges[n][2];
    for (int i = 0; i < n; i++) {
        scanf("%d %d", &edges[i][0], &edges[i][1]);
    }

    printf("%d\n", getResult(edges, m, n));
    return 0;
}

代码讲解

  1. 数据结构

    • 使用邻接表表示图,Graph 结构体中包含一个指针数组 adjList,用于存储每个节点的邻接节点。
    • Node 结构体表示邻接表中的节点。
  2. 图的构建

    • 使用 addEdge 函数将边添加到图中。
  3. DFS 实现

    • dfs 函数用于枚举所有可能的染红节点组合。
    • 使用 isRed 数组标记哪些节点被染成红色。
    • 如果当前节点可以染成红色,则尝试染红并递归。
  4. 边界处理

    • 如果某个节点没有相邻节点,则直接跳过相邻节点检查。
    • 递归结束后,返回染色方案数。
  5. 性能分析

    • 时间复杂度:O(2^m),适合 m <= 15 的情况。
    • 空间复杂度:O(m + n),用于存储邻接表和递归栈。

总结

  • C++ 版本:使用 STL 容器(如 unordered_mapunordered_set)简化了代码实现。
  • C 语言版本:手动实现邻接表和递归逻辑,适合对内存和性能有更高要求的场景。
  • 两种版本的核心思想相同,都是通过 DFS 枚举所有可能的染色方案,并通过剪枝优化性能。

六、尾言

什么是华为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 或监考人员进行反馈。

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

;