一、问题描述
问题描述
给定一个多线段的坐标列表,每个坐标由行号和列号表示。多线段的走向只能是水平、竖直或斜向45度。输入数据包含冗余的坐标点,要求输出最简化的坐标列表,仅保留起点、拐点和终点。
输入描述
- 输入数据为多线段的坐标列表,每两个数字一组,分别表示行号和列号。
- 所有数字以空格分隔。
- 行号和列号范围为 [0, 64),输入数据保证不会越界。
- 输入数据至少包含两个坐标点。
输出描述
- 输出压缩后的最简化坐标列表,格式与输入相同。
- 输出的坐标相对顺序不能变化。
示例
输入
2 8 3 7 3 6 3 5 4 4 5 3 6 2 7 3 8 4 7 5
输出
2 8 3 7 3 5 6 2 8 4 7 5
解题思路
1. 问题分析
本题的核心是识别多线段中的关键点(起点、拐点和终点),并去除冗余的中间点。关键点的特征是运动方向发生变化的点。
2. 运动方向的表示
- 从点 A 到点 B 的运动方向可以用向量表示,即
(offsetX, offsetY)
,其中:offsetX = B.x - A.x
offsetY = B.y - A.y
- 为了简化方向比较,需要将向量归一化。归一化的方法是:
- 计算
base = max(abs(offsetX), abs(offsetY))
- 将向量
(offsetX, offsetY)
简化为(offsetX / base, offsetY / base)
- 计算
3. 拐点的判断
- 对于连续三个点 A、B、C:
- 计算 A→B 的方向向量
dir1
。 - 计算 B→C 的方向向量
dir2
。 - 如果
dir1
和dir2
不相同,则 B 是拐点。
- 计算 A→B 的方向向量
4. 算法步骤
- 初始化:
- 将输入数据解析为坐标列表。
- 将起点加入结果列表。
- 遍历坐标列表:
- 对于每个点,计算其与前一个点的方向向量。
- 如果当前方向向量与前一个方向向量不同,则将前一个点加入结果列表。
- 结束:
- 将终点加入结果列表。
- 输出结果:
- 输出结果列表中的坐标。
关键点解析
1. 方向向量的归一化
- 方向向量的归一化是为了统一表示相同方向的不同向量。例如:
- 向量
(3, -3)
和(1, -1)
表示相同的方向。 - 通过归一化,可以将
(3, -3)
简化为(1, -1)
。
- 向量
2. 拐点的判断
- 拐点的判断基于运动方向的变化。如果当前方向与前一个方向不同,则当前点是拐点。
- 例如:
- A→B 的方向为
(1, -1)
,B→C 的方向为(1, 0)
,则 B 是拐点。
- A→B 的方向为
3. 输出顺序
- 输出的坐标顺序必须与输入顺序一致,不能改变。
示例解析
输入
2 8 3 7 3 6 3 5 4 4 5 3 6 2 7 3 8 4 7 5
处理过程
- 起点:
(2, 8)
加入结果列表。 - 方向变化:
(2, 8)
→(3, 7)
:方向为(1, -1)
。(3, 7)
→(3, 6)
:方向为(0, -1)
,方向变化,(3, 7)
是拐点。(3, 6)
→(3, 5)
:方向为(0, -1)
,方向未变化。(3, 5)
→(4, 4)
:方向为(1, -1)
,方向变化,(3, 5)
是拐点。(4, 4)
→(5, 3)
:方向为(1, -1)
,方向未变化。(5, 3)
→(6, 2)
:方向为(1, -1)
,方向未变化。(6, 2)
→(7, 3)
:方向为(1, 1)
,方向变化,(6, 2)
是拐点。(7, 3)
→(8, 4)
:方向为(1, 1)
,方向未变化。(8, 4)
→(7, 5)
:方向为(-1, 1)
,方向变化,(8, 4)
是拐点。
- 终点:
(7, 5)
加入结果列表。
输出
2 8 3 7 3 5 6 2 8 4 7 5
总结
本题的核心是通过方向向量的变化识别拐点,并去除冗余的中间点。通过归一化方向向量,可以简化方向比较的逻辑。最终输出的坐标列表必须保持与输入相同的顺序。
二、JavaScript算法源码
这段代码实现了对多线段坐标列表的简化,仅保留起点、拐点和终点。以下是对代码的详细解析:
代码结构
-
输入处理:
- 使用
readline
模块读取输入,并将输入拆分为数字数组nums
。 - 调用
getResult
函数处理输入数据,并输出结果。
- 使用
-
主函数
getResult
:- 初始化结果数组
ans
,用于存储简化后的坐标。 - 定义变量
preX
和preY
,表示上一个点的坐标。 - 定义变量
preDirectX
和preDirectY
,表示上一次的运动方向。 - 遍历输入坐标列表,计算当前点的运动方向,并与上一次的运动方向进行比较:
- 如果方向不同,则上一个点是拐点,将其加入结果数组。
- 更新
preX
、preY
、preDirectX
和preDirectY
。
- 遍历结束后,将最后一个点(终点)加入结果数组。
- 返回结果数组,格式为空格分隔的字符串。
- 初始化结果数组
代码逻辑解析
1. 输入处理
- 输入数据为多线段的坐标列表,每两个数字表示一个点的行号和列号。
- 使用
split(" ")
将输入字符串拆分为数字数组nums
。
2. 初始化
preX
和preY
初始化为第一个点的坐标。preDirectX
和preDirectY
初始化为0
,表示初始方向未定义。
3. 遍历坐标列表
- 从第二个点开始遍历,每次取两个数字作为当前点的坐标
(curX, curY)
。 - 计算当前点与上一个点的偏移量
(offsetX, offsetY)
:offsetX = curX - preX
offsetY = curY - preY
- 根据偏移量计算当前运动方向
(directX, directY)
:base = max(abs(offsetX), abs(offsetY))
directX = offsetX / base
directY = offsetY / base
- 比较当前方向与上一次方向:
- 如果方向不同,则上一个点是拐点,将其加入结果数组。
- 更新
preX
、preY
、preDirectX
和preDirectY
。
4. 收尾处理
- 遍历结束后,将最后一个点(终点)加入结果数组。
5. 输出结果
- 将结果数组转换为空格分隔的字符串并返回。
示例运行
输入
2 8 3 7 3 6 3 5 4 4 5 3 6 2 7 3 8 4 7 5
处理过程
- 起点:
(2, 8)
。 - 方向变化:
(2, 8)
→(3, 7)
:方向为(1, -1)
。(3, 7)
→(3, 6)
:方向为(0, -1)
,方向变化,(3, 7)
是拐点。(3, 6)
→(3, 5)
:方向为(0, -1)
,方向未变化。(3, 5)
→(4, 4)
:方向为(1, -1)
,方向变化,(3, 5)
是拐点。(4, 4)
→(5, 3)
:方向为(1, -1)
,方向未变化。(5, 3)
→(6, 2)
:方向为(1, -1)
,方向未变化。(6, 2)
→(7, 3)
:方向为(1, 1)
,方向变化,(6, 2)
是拐点。(7, 3)
→(8, 4)
:方向为(1, 1)
,方向未变化。(8, 4)
→(7, 5)
:方向为(-1, 1)
,方向变化,(8, 4)
是拐点。
- 终点:
(7, 5)
。
输出
2 8 3 7 3 5 6 2 8 4 7 5
代码优化建议
-
变量命名:
- 可以将
preX
和preY
合并为一个对象prevPoint = { x, y }
,提高代码可读性。 - 可以将
preDirectX
和preDirectY
合并为一个对象prevDirection = { x, y }
。
- 可以将
-
边界检查:
- 如果输入数据不足两个点,可以直接返回空数组或提示错误。
-
性能优化:
- 如果输入数据量较大,可以考虑使用更高效的数据结构或算法。
总结
这段代码通过遍历坐标列表,计算运动方向并识别拐点,最终输出了简化后的坐标列表。代码逻辑清晰,能够正确处理各种边界情况,适合学习和参考。
三、Java算法源码
以下是对 Java 代码的详细注释和讲解:
代码结构
-
主函数
main
:- 使用
Scanner
读取输入,并将输入拆分为整数数组nums
。 - 调用
getResult
函数处理输入数据,并输出结果。
- 使用
-
主逻辑函数
getResult
:- 使用
StringJoiner
存储简化后的坐标列表。 - 定义变量
preX
和preY
,表示上一个点的坐标。 - 定义变量
preDirectX
和preDirectY
,表示上一次的运动方向。 - 遍历输入坐标列表,计算当前点的运动方向,并与上一次的运动方向进行比较:
- 如果方向不同,则上一个点是拐点,将其加入结果列表。
- 更新
preX
、preY
、preDirectX
和preDirectY
。
- 遍历结束后,将最后一个点(终点)加入结果列表。
- 返回结果列表,格式为空格分隔的字符串。
- 使用
代码逻辑解析
1. 输入处理
- 使用
Scanner
读取输入,并通过split(" ")
将输入字符串拆分为字符串数组。 - 使用
Arrays.stream
和mapToInt
将字符串数组转换为整数数组nums
。
2. 初始化
- 创建
StringJoiner
对象sj
,用于存储简化后的坐标列表。 preX
和preY
初始化为第一个点的坐标。preDirectX
和preDirectY
初始化为0
,表示初始方向未定义。
3. 遍历坐标列表
- 从第二个点开始遍历,每次取两个数字作为当前点的坐标
(curX, curY)
。 - 计算当前点与上一个点的偏移量
(offsetX, offsetY)
:offsetX = curX - preX
offsetY = curY - preY
- 根据偏移量计算当前运动方向
(directX, directY)
:base = max(abs(offsetX), abs(offsetY))
directX = offsetX / base
directY = offsetY / base
- 比较当前方向与上一次方向:
- 如果方向不同,则上一个点是拐点,将其加入结果列表。
- 更新
preX
、preY
、preDirectX
和preDirectY
。
4. 收尾处理
- 遍历结束后,将最后一个点(终点)加入结果列表。
5. 输出结果
- 使用
StringJoiner
的toString
方法将结果列表转换为空格分隔的字符串并返回。
代码详细注释
import java.util.Arrays;
import java.util.Scanner;
import java.util.StringJoiner;
public class Main {
public static void main(String[] args) {
// 创建Scanner对象,用于读取输入
Scanner sc = new Scanner(System.in);
// 读取输入并拆分为整数数组
int[] nums = Arrays.stream(sc.nextLine().split(" ")).mapToInt(Integer::parseInt).toArray();
// 调用getResult函数并输出结果
System.out.println(getResult(nums));
}
public static String getResult(int[] nums) {
// 创建StringJoiner对象,用于存储简化后的坐标列表
StringJoiner sj = new StringJoiner(" ");
// 上一个点坐标(preX, preY)
int preX = nums[0];
int preY = nums[1];
// 上一次的运动方向(preDirectX, preDirectY)
int preDirectX = 0;
int preDirectY = 0;
// 遍历坐标列表,从第二个点开始
for (int i = 2; i < nums.length; i += 2) {
// 当前点坐标(curX, curY)
int curX = nums[i];
int curY = nums[i + 1];
// 上一个点到当前点的偏移量(offsetX, offsetY)
int offsetX = curX - preX;
int offsetY = curY - preY;
// 根据偏移量得出本次的运动方向
int base = Math.max(Math.abs(offsetX), Math.abs(offsetY));
int directX = offsetX / base;
int directY = offsetY / base;
// 如果两次运动的方向不同
if (directX != preDirectX || directY != preDirectY) {
// 则上一个点是拐点,需要记录下来
sj.add(preX + " " + preY);
}
// 更新上一个点的坐标和方向
preX = curX;
preY = curY;
preDirectX = directX;
preDirectY = directY;
}
// 注意收尾,将最后一个点(终点)加入结果列表
sj.add(preX + " " + preY);
// 返回结果列表
return sj.toString();
}
}
示例运行
输入
2 8 3 7 3 6 3 5 4 4 5 3 6 2 7 3 8 4 7 5
处理过程
- 起点:
(2, 8)
。 - 方向变化:
(2, 8)
→(3, 7)
:方向为(1, -1)
。(3, 7)
→(3, 6)
:方向为(0, -1)
,方向变化,(3, 7)
是拐点。(3, 6)
→(3, 5)
:方向为(0, -1)
,方向未变化。(3, 5)
→(4, 4)
:方向为(1, -1)
,方向变化,(3, 5)
是拐点。(4, 4)
→(5, 3)
:方向为(1, -1)
,方向未变化。(5, 3)
→(6, 2)
:方向为(1, -1)
,方向未变化。(6, 2)
→(7, 3)
:方向为(1, 1)
,方向变化,(6, 2)
是拐点。(7, 3)
→(8, 4)
:方向为(1, 1)
,方向未变化。(8, 4)
→(7, 5)
:方向为(-1, 1)
,方向变化,(8, 4)
是拐点。
- 终点:
(7, 5)
。
输出
2 8 3 7 3 5 6 2 8 4 7 5
总结
这段代码通过遍历坐标列表,计算运动方向并识别拐点,最终输出了简化后的坐标列表。代码逻辑清晰,能够正确处理各种边界情况,适合学习和参考。
四、Python算法源码
以下是对 Python 代码的详细注释和讲解:
代码结构
-
输入处理:
- 使用
input().split()
读取输入,并将输入拆分为整数列表nums
。
- 使用
-
主逻辑函数
getResult
:- 初始化结果列表
ans
,用于存储简化后的坐标。 - 定义变量
preX
和preY
,表示上一个点的坐标。 - 定义变量
preDirectX
和preDirectY
,表示上一次的运动方向。 - 遍历输入坐标列表,计算当前点的运动方向,并与上一次的运动方向进行比较:
- 如果方向不同,则上一个点是拐点,将其加入结果列表。
- 更新
preX
、preY
、preDirectX
和preDirectY
。
- 遍历结束后,将最后一个点(终点)加入结果列表。
- 返回结果列表,格式为空格分隔的字符串。
- 初始化结果列表
-
算法调用:
- 调用
getResult
函数并输出结果。
- 调用
代码逻辑解析
1. 输入处理
- 使用
input().split()
将输入字符串拆分为字符串列表。 - 使用
map(int, ...)
将字符串列表转换为整数列表nums
。
2. 初始化
- 创建空列表
ans
,用于存储简化后的坐标。 preX
和preY
初始化为第一个点的坐标。preDirectX
和preDirectY
初始化为0
,表示初始方向未定义。
3. 遍历坐标列表
- 从第二个点开始遍历,每次取两个数字作为当前点的坐标
(curX, curY)
。 - 计算当前点与上一个点的偏移量
(offsetX, offsetY)
:offsetX = curX - preX
offsetY = curY - preY
- 根据偏移量计算当前运动方向
(directX, directY)
:base = max(abs(offsetX), abs(offsetY))
directX = offsetX // base
directY = offsetY // base
- 比较当前方向与上一次方向:
- 如果方向不同,则上一个点是拐点,将其加入结果列表。
- 更新
preX
、preY
、preDirectX
和preDirectY
。
4. 收尾处理
- 遍历结束后,将最后一个点(终点)加入结果列表。
5. 输出结果
- 使用
map(str, ans)
将结果列表中的整数转换为字符串。 - 使用
" ".join(...)
将字符串列表拼接为空格分隔的字符串并返回。
代码详细注释
# 输入获取
nums = list(map(int, input().split()))
# 算法入口
def getResult():
ans = []
# 上一个点坐标(preX, preY)
preX = nums[0]
preY = nums[1]
# 上一次的运动方向(preDirectX, preDirectY)
preDirectX = 0
preDirectY = 0
# 遍历坐标列表,从第二个点开始
for i in range(2, len(nums), 2):
# 当前点坐标(curX, curY)
curX = nums[i]
curY = nums[i + 1]
# 上一个点到当前点的偏移量(offsetX, offsetY)
offsetX = curX - preX
offsetY = curY - preY
# 根据偏移量得出本次的运动方向
base = max(abs(offsetX), abs(offsetY))
directX = offsetX // base
directY = offsetY // base
# 如果两次运动的方向不同
if directX != preDirectX or directY != preDirectY:
# 则上一个点是拐点,需要记录下来
ans.extend([preX, preY])
# 更新上一个点的坐标和方向
preX = curX
preY = curY
preDirectX = directX
preDirectY = directY
# 注意收尾,将最后一个点(终点)加入结果列表
ans.extend([preX, preY])
# 返回结果列表
return " ".join(map(str, ans))
# 算法调用
print(getResult())
示例运行
输入
2 8 3 7 3 6 3 5 4 4 5 3 6 2 7 3 8 4 7 5
处理过程
- 起点:
(2, 8)
。 - 方向变化:
(2, 8)
→(3, 7)
:方向为(1, -1)
。(3, 7)
→(3, 6)
:方向为(0, -1)
,方向变化,(3, 7)
是拐点。(3, 6)
→(3, 5)
:方向为(0, -1)
,方向未变化。(3, 5)
→(4, 4)
:方向为(1, -1)
,方向变化,(3, 5)
是拐点。(4, 4)
→(5, 3)
:方向为(1, -1)
,方向未变化。(5, 3)
→(6, 2)
:方向为(1, -1)
,方向未变化。(6, 2)
→(7, 3)
:方向为(1, 1)
,方向变化,(6, 2)
是拐点。(7, 3)
→(8, 4)
:方向为(1, 1)
,方向未变化。(8, 4)
→(7, 5)
:方向为(-1, 1)
,方向变化,(8, 4)
是拐点。
- 终点:
(7, 5)
。
输出
2 8 3 7 3 5 6 2 8 4 7 5
总结
这段代码通过遍历坐标列表,计算运动方向并识别拐点,最终输出了简化后的坐标列表。代码逻辑清晰,能够正确处理各种边界情况,适合学习和参考。
五、C/C++算法源码:
以下是 C++ 和 C语言 版本的代码实现,并附带详细的中文注释和讲解。
C++ 版本
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
int main() {
vector<int> nums; // 存储输入坐标的数组
int num;
// 读取输入,直到遇到换行符
while (cin >> num) {
nums.push_back(num);
if (cin.get() != ' ') break; // 如果下一个字符不是空格,则结束输入
}
// 上一个点坐标(preX, preY)
int preX = nums[0];
int preY = nums[1];
// 上一次的运动方向(preDirectX, preDirectY)
int preDirectX = 0;
int preDirectY = 0;
// 遍历坐标列表,从第二个点开始
for (int i = 2; i < nums.size(); i += 2) {
// 当前点坐标(curX, curY)
int curX = nums[i];
int curY = nums[i + 1];
// 上一个点到当前点的偏移量(offsetX, offsetY)
int offsetX = curX - preX;
int offsetY = curY - preY;
// 根据偏移量得出本次的运动方向
int base = max(abs(offsetX), abs(offsetY));
int directX = offsetX / base;
int directY = offsetY / base;
// 如果两次运动的方向不同
if (directX != preDirectX || directY != preDirectY) {
// 则上一个点是拐点,需要记录下来
cout << preX << " " << preY << " ";
}
// 更新上一个点的坐标和方向
preX = curX;
preY = curY;
preDirectX = directX;
preDirectY = directY;
}
// 注意收尾,将最后一个点(终点)输出
cout << preX << " " << preY;
return 0;
}
C语言版本
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define MAX_SIZE 20000 // 定义最大输入长度
int main() {
int nums[MAX_SIZE]; // 存储输入坐标的数组
int nums_size = 0; // 输入坐标的数量
// 读取输入,直到遇到换行符
while (scanf("%d", &nums[nums_size++])) {
if (getchar() != ' ') break; // 如果下一个字符不是空格,则结束输入
}
// 上一个点坐标(preX, preY)
int preX = nums[0];
int preY = nums[1];
// 上一次的运动方向(preDirectX, preDirectY)
int preDirectX = 0;
int preDirectY = 0;
// 遍历坐标列表,从第二个点开始
for (int i = 2; i < nums_size; i += 2) {
// 当前点坐标(curX, curY)
int curX = nums[i];
int curY = nums[i + 1];
// 上一个点到当前点的偏移量(offsetX, offsetY)
int offsetX = curX - preX;
int offsetY = curY - preY;
// 根据偏移量得出本次的运动方向
int base = (int) fmax(abs(offsetX), abs(offsetY));
int directX = offsetX / base;
int directY = offsetY / base;
// 如果两次运动的方向不同
if (directX != preDirectX || directY != preDirectY) {
// 则上一个点是拐点,需要记录下来
printf("%d %d ", preX, preY);
}
// 更新上一个点的坐标和方向
preX = curX;
preY = curY;
preDirectX = directX;
preDirectY = directY;
}
// 注意收尾,将最后一个点(终点)输出
printf("%d %d", preX, preY);
return 0;
}
代码详细注释
1. 输入处理
- C++:
- 使用
vector<int>
动态存储输入坐标。 - 使用
cin
读取输入,直到遇到换行符。
- 使用
- C语言:
- 使用固定大小的数组
nums
存储输入坐标。 - 使用
scanf
读取输入,直到遇到换行符。
- 使用固定大小的数组
2. 初始化
preX
和preY
初始化为第一个点的坐标。preDirectX
和preDirectY
初始化为0
,表示初始方向未定义。
3. 遍历坐标列表
- 从第二个点开始遍历,每次取两个数字作为当前点的坐标
(curX, curY)
。 - 计算当前点与上一个点的偏移量
(offsetX, offsetY)
:offsetX = curX - preX
offsetY = curY - preY
- 根据偏移量计算当前运动方向
(directX, directY)
:base = max(abs(offsetX), abs(offsetY))
directX = offsetX / base
directY = offsetY / base
- 比较当前方向与上一次方向:
- 如果方向不同,则上一个点是拐点,将其输出。
4. 收尾处理
- 遍历结束后,将最后一个点(终点)输出。
示例运行
输入
2 8 3 7 3 6 3 5 4 4 5 3 6 2 7 3 8 4 7 5
处理过程
- 起点:
(2, 8)
。 - 方向变化:
(2, 8)
→(3, 7)
:方向为(1, -1)
。(3, 7)
→(3, 6)
:方向为(0, -1)
,方向变化,(3, 7)
是拐点。(3, 6)
→(3, 5)
:方向为(0, -1)
,方向未变化。(3, 5)
→(4, 4)
:方向为(1, -1)
,方向变化,(3, 5)
是拐点。(4, 4)
→(5, 3)
:方向为(1, -1)
,方向未变化。(5, 3)
→(6, 2)
:方向为(1, -1)
,方向未变化。(6, 2)
→(7, 3)
:方向为(1, 1)
,方向变化,(6, 2)
是拐点。(7, 3)
→(8, 4)
:方向为(1, 1)
,方向未变化。(8, 4)
→(7, 5)
:方向为(-1, 1)
,方向变化,(8, 4)
是拐点。
- 终点:
(7, 5)
。
输出
2 8 3 7 3 5 6 2 8 4 7 5
总结
这段代码通过遍历坐标列表,计算运动方向并识别拐点,最终输出了简化后的坐标列表。代码逻辑清晰,能够正确处理各种边界情况,适合学习和参考。
六、尾言
什么是华为OD?
华为OD(Outsourcing Developer,外包开发工程师)是华为针对软件开发工程师岗位的一种招聘形式,主要包括笔试、技术面试以及综合面试等环节。尤其在笔试部分,算法题的机试至关重要。
为什么刷题很重要?
-
机试是进入技术面的第一关:
华为OD机试(常被称为机考)主要考察算法和编程能力。只有通过机试,才能进入后续的技术面试环节。 -
技术面试需要手撕代码:
技术一面和二面通常会涉及现场编写代码或算法题。面试官会注重考察候选人的思路清晰度、代码规范性以及解决问题的能力。因此提前刷题、多练习是通过面试的重要保障。 -
入职后的可信考试:
入职华为后,还需要通过“可信考试”。可信考试分为三个等级:- 入门级:主要考察基础算法与编程能力。
- 工作级:更贴近实际业务需求,可能涉及复杂的算法或与工作内容相关的场景题目。
- 专业级:最高等级,考察深层次的算法以及优化能力,与薪资直接挂钩。
刷题策略与说明:
2024年8月14日之后,华为OD机试的题库转为 E卷,由往年题库(D卷、A卷、B卷、C卷)和全新题目组成。刷题时可以参考以下策略:
-
关注历年真题:
- 题库中的旧题占比较大,建议优先刷历年的A卷、B卷、C卷、D卷题目。
- 对于每道题目,建议深度理解其解题思路、代码实现,以及相关算法的适用场景。
-
适应新题目:
- E卷中包含全新题目,需要掌握全面的算法知识和一定的灵活应对能力。
- 建议关注新的刷题平台或交流群,获取最新题目的解析和动态。
-
掌握常见算法:
华为OD考试通常涉及以下算法和数据结构:- 排序算法(快速排序、归并排序等)
- 动态规划(背包问题、最长公共子序列等)
- 贪心算法
- 栈、队列、链表的操作
- 图论(最短路径、最小生成树等)
- 滑动窗口、双指针算法
-
保持编程规范:
- 注重代码的可读性和注释的清晰度。
- 熟练使用常见编程语言,如C++、Java、Python等。
如何获取资源?
-
官方参考:
- 华为招聘官网或相关的招聘平台会有一些参考信息。
- 华为OD的相关公众号可能也会发布相关的刷题资料或学习资源。
-
加入刷题社区:
- 找到可信的刷题交流群,与其他备考的小伙伴交流经验。
- 关注知名的刷题网站,如LeetCode、牛客网等,这些平台上有许多华为OD的历年真题和解析。
-
寻找系统性的教程:
- 学习一本经典的算法书籍,例如《算法导论》《剑指Offer》《编程之美》等。
- 完成系统的学习课程,例如数据结构与算法的在线课程。
积极心态与持续努力:
刷题的过程可能会比较枯燥,但它能够显著提升编程能力和算法思维。无论是为了通过华为OD的招聘考试,还是为了未来的职业发展,这些积累都会成为重要的财富。
考试注意细节
-
本地编写代码
- 在本地 IDE(如 VS Code、PyCharm 等)上编写、保存和调试代码,确保逻辑正确后再复制粘贴到考试页面。这样可以减少语法错误,提高代码准确性。
-
调整心态,保持冷静
- 遇到提示不足或实现不确定的问题时,不必慌张,可以采用更简单或更有把握的方法替代,确保思路清晰。
-
输入输出完整性
- 注意训练和考试时都需要编写完整的输入输出代码,尤其是和题目示例保持一致。完成代码后务必及时调试,确保功能符合要求。
-
快捷键使用
- 删除行可用
Ctrl+D
,复制、粘贴和撤销分别为Ctrl+C
,Ctrl+V
,Ctrl+Z
,这些可以正常使用。 - 避免使用
Ctrl+S
,以免触发浏览器的保存功能。
- 删除行可用
-
浏览器要求
- 使用最新版的 Google Chrome 浏览器完成考试,确保摄像头开启并正常工作。考试期间不要切换到其他网站,以免影响考试成绩。
-
交卷相关
- 答题前,务必仔细查看题目示例,避免遗漏要求。
- 每完成一道题后,点击【保存并调试】按钮,多次保存和调试是允许的,系统会记录得分最高的一次结果。完成所有题目后,点击【提交本题型】按钮。
- 确保在考试结束前提交试卷,避免因未保存或调试失误而丢分。
-
时间和分数安排
- 总时间:150 分钟;总分:400 分。
- 试卷结构:2 道一星难度题(每题 100 分),1 道二星难度题(200 分)。及格分为 150 分。合理分配时间,优先完成自己擅长的题目。
-
考试环境准备
- 考试前请备好草稿纸和笔。考试中尽量避免离开座位,确保监控画面正常。
- 如需上厕所,请提前规划好时间以减少中途离开监控的可能性。
-
技术问题处理
- 如果考试中遇到断电、断网、死机等技术问题,可以关闭浏览器并重新打开试卷链接继续作答。
- 出现其他问题,请第一时间联系 HR 或监考人员进行反馈。
祝你考试顺利,取得理想成绩!