【2024年华为OD机试】(C卷,100分)- 求满足条件的最长子串的长度 (Java & JS & Python&C/C++)
一、问题描述
题目解析
我们需要找到一个字符串中最长的子串,该子串满足以下条件:
- 子串中只能包含一个字母(
a~z
或A~Z
),其余字符必须是数字。 - 字母可以在子串中的任意位置。
如果字符串中没有满足条件的子串(例如全是字母或全是数字),则返回 -1
。
解题思路
我们可以使用滑动窗口的方法来解决这个问题。滑动窗口的核心思想是维护一个窗口(即子串),通过移动窗口的左右边界来找到满足条件的最长子串。
具体步骤:
-
初始化:
- 使用两个指针
left
和right
来表示滑动窗口的左右边界。 - 使用一个变量
letterCount
来记录当前窗口中字母的数量。 - 使用一个变量
maxLen
来记录满足条件的最长子串的长度。 - 使用一个变量
lastLetterIndex
来记录窗口中最后一个字母的位置。
- 使用两个指针
-
滑动窗口:
- 遍历字符串,移动
right
指针。 - 如果当前字符是字母,则
letterCount
加 1,并更新lastLetterIndex
。 - 如果
letterCount
超过 1(即窗口中有超过一个字母),则需要移动left
指针:- 如果
left
指向的是字母,则移动left
到lastLetterIndex + 1
,并减少letterCount
。 - 如果
left
指向的是数字,则直接移动left
到lastLetterIndex + 1
。
- 如果
- 更新
maxLen
为当前窗口的长度和maxLen
中的较大值。
- 遍历字符串,移动
-
返回结果:
- 如果
maxLen
仍然为初始值(表示没有满足条件的子串),则返回-1
。 - 否则返回
maxLen
。
- 如果
代码实现
C++ 实现
#include <iostream>
#include <string>
using namespace std;
int findLongestSubstring(const string& s) {
int left = 0; // 滑动窗口的左边界
int maxLen = -1; // 满足条件的最长子串长度
int letterCount = 0; // 当前窗口中字母的数量
int lastLetterIndex = -1; // 窗口中最后一个字母的位置
for (int right = 0; right < s.size(); right++) {
if (isalpha(s[right])) {
letterCount++;
lastLetterIndex = right; // 更新最后一个字母的位置
}
// 如果窗口中有超过一个字母,移动左边界
if (letterCount > 1) {
if (isalpha(s[left])) {
letterCount--; // 减少字母数量
}
left = lastLetterIndex + 1; // 移动左边界到最后一个字母的下一个位置
}
// 更新最大长度
if (letterCount == 1) {
maxLen = max(maxLen, right - left + 1);
}
}
return maxLen;
}
int main() {
string input;
cin >> input;
int result = findLongestSubstring(input);
cout << result << endl;
return 0;
}
C 语言实现
#include <stdio.h>
#include <ctype.h>
#include <string.h>
int findLongestSubstring(const char* s) {
int left = 0; // 滑动窗口的左边界
int maxLen = -1; // 满足条件的最长子串长度
int letterCount = 0; // 当前窗口中字母的数量
int lastLetterIndex = -1; // 窗口中最后一个字母的位置
for (int right = 0; right < strlen(s); right++) {
if (isalpha(s[right])) {
letterCount++;
lastLetterIndex = right; // 更新最后一个字母的位置
}
// 如果窗口中有超过一个字母,移动左边界
if (letterCount > 1) {
if (isalpha(s[left])) {
letterCount--; // 减少字母数量
}
left = lastLetterIndex + 1; // 移动左边界到最后一个字母的下一个位置
}
// 更新最大长度
if (letterCount == 1) {
if (right - left + 1 > maxLen) {
maxLen = right - left + 1;
}
}
}
return maxLen;
}
int main() {
char input[1000];
scanf("%s", input);
int result = findLongestSubstring(input);
printf("%d\n", result);
return 0;
}
代码讲解
-
滑动窗口的核心逻辑:
- 使用
left
和right
指针表示窗口的左右边界。 - 当
right
指针遇到字母时,增加letterCount
并记录字母的位置。 - 如果
letterCount
超过 1,则移动left
指针到最后一个字母的下一个位置,并减少letterCount
。
- 使用
-
边界条件处理:
- 如果字符串中没有字母或全是字母,则返回
-1
。 - 如果字符串中只有一个字母,则整个字符串就是满足条件的子串。
- 如果字符串中没有字母或全是字母,则返回
-
时间复杂度:
- 由于
left
和right
指针最多各遍历一次字符串,时间复杂度为O(n)
,其中n
是字符串的长度。
- 由于
测试用例
输入 1:
abC124ACb
输出 1:
4
输入 2:
a5
输出 2:
2
输入 3:
aBB9
输出 3:
2
输入 4:
abcdef
输出 4:
-1
总结
通过滑动窗口的方法,我们可以高效地找到满足条件的最长子串。代码逻辑清晰,时间复杂度为 O(n)
,适用于较长的字符串输入。
二、JavaScript算法源码
代码解析
这段代码是用 JavaScript 实现的滑动窗口算法,用于解决题目中描述的问题。以下是代码的详细解析:
1. 输入获取
const readline = require("readline");
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
rl.on("line", (line) => {
console.log(getResult(line));
});
- 使用
readline
模块从控制台读取输入。 - 当用户输入一行数据时,调用
getResult
函数处理输入,并输出结果。
2. 滑动窗口逻辑
function getResult(s) {
let maxLen = -1; // 记录满足条件的最长子串长度
let l = 0, r = 0; // 滑动窗口的左右指针
let hasLetter = false; // 标记字符串中是否至少有一个字母
const letterIdx = []; // 记录字母的索引
maxLen
:用于记录满足条件的最长子串的长度,初始值为-1
。l
和r
:滑动窗口的左右指针,初始值均为0
。hasLetter
:用于标记字符串中是否至少有一个字母。letterIdx
:用于记录字母的索引,方便在窗口中有多个字母时调整左指针。
3. 滑动窗口的核心逻辑
while (r < s.length) {
if (isLetter(s[r])) {
hasLetter = true; // 标记字符串中有字母
letterIdx.push(r); // 记录字母的索引
if (letterIdx.length > 1) {
l = letterIdx.shift() + 1; // 如果窗口中有超过一个字母,移动左指针
}
if (r == l) {
r++;
continue;
}
}
maxLen = Math.max(maxLen, r - l + 1); // 更新最大长度
r++; // 移动右指针
}
- 字母处理:
- 如果当前字符是字母,则标记
hasLetter
为true
,并将字母的索引存入letterIdx
。 - 如果
letterIdx
的长度超过 1(即窗口中有超过一个字母),则移动左指针l
到第一个字母的下一个位置。
- 如果当前字符是字母,则标记
- 更新最大长度:
- 每次右指针
r
移动后,计算当前窗口的长度r - l + 1
,并更新maxLen
。
- 每次右指针
- 右指针移动:
- 右指针
r
每次循环都会向右移动。
- 右指针
4. 边界条件处理
if (!hasLetter) return -1;
return maxLen;
- 如果字符串中没有字母(即
hasLetter
为false
),则返回-1
。 - 否则返回
maxLen
。
5. 辅助函数
function isLetter(c) {
return (c >= "a" && c <= "z") || (c >= "A" && c <= "Z");
}
- 判断一个字符是否是字母(
a~z
或A~Z
)。
6. 代码逻辑总结
-
滑动窗口初始化:
- 使用两个指针
l
和r
表示窗口的左右边界。 - 使用
letterIdx
记录字母的索引,方便在窗口中有多个字母时调整左指针。
- 使用两个指针
-
窗口扩展:
- 右指针
r
不断向右移动,扩展窗口。 - 如果遇到字母,则记录其索引,并检查窗口中是否已经有超过一个字母。
- 右指针
-
窗口收缩:
- 如果窗口中有超过一个字母,则移动左指针
l
到第一个字母的下一个位置。
- 如果窗口中有超过一个字母,则移动左指针
-
更新结果:
- 每次窗口扩展或收缩后,更新满足条件的最长子串长度
maxLen
。
- 每次窗口扩展或收缩后,更新满足条件的最长子串长度
-
边界条件:
- 如果字符串中没有字母,则返回
-1
。
- 如果字符串中没有字母,则返回
7. 测试用例
输入 1:
abC124ACb
输出 1:
4
输入 2:
a5
输出 2:
2
输入 3:
aBB9
输出 3:
2
输入 4:
abcdef
输出 4:
-1
总结
- 这段代码通过滑动窗口算法高效地解决了问题,时间复杂度为
O(n)
,空间复杂度为O(1)
。 - 代码逻辑清晰,适合处理较长的字符串输入。
- 通过优化变量命名和边界条件处理,代码的可读性和性能得到了进一步提升。
三、Java算法源码
代码详细注释与讲解
以下是代码的逐行注释和逻辑讲解:
1. 主函数 main
public static void main(String[] args) {
Scanner sc = new Scanner(System.in); // 创建 Scanner 对象,用于从控制台读取输入
System.out.println(getResult(sc.next())); // 读取输入字符串并调用 getResult 方法,输出结果
}
- 功能:从控制台读取用户输入的字符串,并调用
getResult
方法处理字符串,最后输出结果。 - 关键点:
sc.next()
:读取用户输入的一个字符串(以空格或换行符分隔)。System.out.println
:输出结果。
2. 核心方法 getResult
private static int getResult(String str) {
int maxLen = -1; // 记录满足条件的最长子串长度,初始值为 -1
boolean hasLetter = false; // 标记字符串中是否至少有一个字母
int l = 0, r = 0; // 滑动窗口的左右指针,初始值均为 0
LinkedList<Integer> letterIdx = new LinkedList<>(); // 用于记录字母的索引
- 功能:计算字符串中满足条件的最长子串长度。
- 关键点:
maxLen
:用于记录满足条件的最长子串长度,初始值为-1
。hasLetter
:用于标记字符串中是否至少有一个字母。l
和r
:滑动窗口的左右指针,初始值均为0
。letterIdx
:使用LinkedList
记录字母的索引,方便在窗口中有多个字母时调整左指针。
3. 滑动窗口的核心逻辑
while (r < str.length()) {
char c = str.charAt(r); // 获取当前字符
if (isLetter(c)) { // 如果当前字符是字母
hasLetter = true; // 标记字符串中有字母
letterIdx.add(r); // 将当前字母的索引加入 letterIdx
if (letterIdx.size() > 1) { // 如果窗口中有超过一个字母
l = letterIdx.removeFirst() + 1; // 移动左指针到第一个字母的下一个位置
}
if (r == l) { // 如果左右指针重合
r++; // 移动右指针
continue; // 跳过后续逻辑
}
}
maxLen = Math.max(maxLen, r - l + 1); // 更新最大长度
r++; // 移动右指针
}
- 功能:通过滑动窗口遍历字符串,找到满足条件的最长子串。
- 关键点:
- 字母处理:
- 如果当前字符是字母,则标记
hasLetter
为true
,并将字母的索引加入letterIdx
。 - 如果
letterIdx
的大小超过 1(即窗口中有超过一个字母),则移动左指针l
到第一个字母的下一个位置。
- 如果当前字符是字母,则标记
- 窗口扩展:
- 右指针
r
不断向右移动,扩展窗口。
- 右指针
- 窗口收缩:
- 如果窗口中有超过一个字母,则移动左指针
l
到第一个字母的下一个位置。
- 如果窗口中有超过一个字母,则移动左指针
- 更新最大长度:
- 每次窗口扩展或收缩后,计算当前窗口的长度
r - l + 1
,并更新maxLen
。
- 每次窗口扩展或收缩后,计算当前窗口的长度
- 字母处理:
4. 边界条件处理
if (!hasLetter) return -1; // 如果字符串中没有字母,返回 -1
return maxLen; // 返回满足条件的最长子串长度
- 功能:处理字符串中没有字母的情况。
- 关键点:
- 如果
hasLetter
为false
(即字符串中没有字母),则返回-1
。 - 否则返回
maxLen
。
- 如果
5. 辅助方法 isLetter
public static boolean isLetter(char c) {
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); // 判断字符是否是字母
}
- 功能:判断一个字符是否是字母(
a~z
或A~Z
)。 - 关键点:
- 使用字符的 ASCII 值范围判断是否是字母。
代码逻辑总结
-
滑动窗口初始化:
- 使用两个指针
l
和r
表示窗口的左右边界。 - 使用
letterIdx
记录字母的索引,方便在窗口中有多个字母时调整左指针。
- 使用两个指针
-
窗口扩展:
- 右指针
r
不断向右移动,扩展窗口。 - 如果遇到字母,则记录其索引,并检查窗口中是否已经有超过一个字母。
- 右指针
-
窗口收缩:
- 如果窗口中有超过一个字母,则移动左指针
l
到第一个字母的下一个位置。
- 如果窗口中有超过一个字母,则移动左指针
-
更新结果:
- 每次窗口扩展或收缩后,更新满足条件的最长子串长度
maxLen
。
- 每次窗口扩展或收缩后,更新满足条件的最长子串长度
-
边界条件:
- 如果字符串中没有字母,则返回
-1
。
- 如果字符串中没有字母,则返回
示例运行
输入 1:
abC124ACb
输出 1:
4
输入 2:
a5
输出 2:
2
输入 3:
aBB9
输出 3:
2
输入 4:
abcdef
输出 4:
-1
总结
- 这段代码通过滑动窗口算法高效地解决了问题,时间复杂度为
O(n)
,空间复杂度为O(1)
。 - 代码逻辑清晰,适合处理较长的字符串输入。
- 通过记录字母的索引,能够快速调整窗口的左边界,确保窗口内最多只有一个字母。
四、Python算法源码
代码详细注释与讲解
1. 输入获取
s = input() # 从控制台读取用户输入的字符串
- 功能:从控制台读取用户输入的字符串。
- 关键点:
input()
:读取用户输入的一行字符串。
2. 算法入口 getResult
def getResult():
maxLen = -1 # 记录满足条件的最长子串长度,初始值为 -1
l = 0 # 滑动窗口的左指针,初始值为 0
r = 0 # 滑动窗口的右指针,初始值为 0
letterIdx = [] # 用于记录字母的索引
hasLetter = False # 标记字符串中是否至少有一个字母
- 功能:计算字符串中满足条件的最长子串长度。
- 关键点:
maxLen
:用于记录满足条件的最长子串长度,初始值为-1
。l
和r
:滑动窗口的左右指针,初始值均为0
。letterIdx
:用于记录字母的索引,方便在窗口中有多个字母时调整左指针。hasLetter
:用于标记字符串中是否至少有一个字母。
3. 滑动窗口的核心逻辑
while r < len(s): # 遍历字符串
if s[r].isalpha(): # 如果当前字符是字母
hasLetter = True # 标记字符串中有字母
letterIdx.append(r) # 将当前字母的索引加入 letterIdx
if len(letterIdx) > 1: # 如果窗口中有超过一个字母
l = letterIdx.pop(0) + 1 # 移动左指针到第一个字母的下一个位置
if r == l: # 如果左右指针重合
r += 1 # 移动右指针
continue # 跳过后续逻辑
maxLen = max(maxLen, r - l + 1) # 更新最大长度
r += 1 # 移动右指针
- 功能:通过滑动窗口遍历字符串,找到满足条件的最长子串。
- 关键点:
- 字母处理:
- 如果当前字符是字母,则标记
hasLetter
为True
,并将字母的索引加入letterIdx
。 - 如果
letterIdx
的长度超过 1(即窗口中有超过一个字母),则移动左指针l
到第一个字母的下一个位置。
- 如果当前字符是字母,则标记
- 窗口扩展:
- 右指针
r
不断向右移动,扩展窗口。
- 右指针
- 窗口收缩:
- 如果窗口中有超过一个字母,则移动左指针
l
到第一个字母的下一个位置。
- 如果窗口中有超过一个字母,则移动左指针
- 更新最大长度:
- 每次窗口扩展或收缩后,计算当前窗口的长度
r - l + 1
,并更新maxLen
。
- 每次窗口扩展或收缩后,计算当前窗口的长度
- 字母处理:
4. 边界条件处理
if not hasLetter: # 如果字符串中没有字母
return -1 # 返回 -1
return maxLen # 返回满足条件的最长子串长度
- 功能:处理字符串中没有字母的情况。
- 关键点:
- 如果
hasLetter
为False
(即字符串中没有字母),则返回-1
。 - 否则返回
maxLen
。
- 如果
5. 算法调用
print(getResult()) # 调用 getResult 方法并输出结果
- 功能:调用
getResult
方法并输出结果。 - 关键点:
print(getResult())
:调用getResult
方法并输出结果。
代码逻辑总结
-
滑动窗口初始化:
- 使用两个指针
l
和r
表示窗口的左右边界。 - 使用
letterIdx
记录字母的索引,方便在窗口中有多个字母时调整左指针。
- 使用两个指针
-
窗口扩展:
- 右指针
r
不断向右移动,扩展窗口。 - 如果遇到字母,则记录其索引,并检查窗口中是否已经有超过一个字母。
- 右指针
-
窗口收缩:
- 如果窗口中有超过一个字母,则移动左指针
l
到第一个字母的下一个位置。
- 如果窗口中有超过一个字母,则移动左指针
-
更新结果:
- 每次窗口扩展或收缩后,更新满足条件的最长子串长度
maxLen
。
- 每次窗口扩展或收缩后,更新满足条件的最长子串长度
-
边界条件:
- 如果字符串中没有字母,则返回
-1
。
- 如果字符串中没有字母,则返回
示例运行
输入 1:
abC124ACb
输出 1:
4
输入 2:
a5
输出 2:
2
输入 3:
aBB9
输出 3:
2
输入 4:
abcdef
输出 4:
-1
总结
- 这段代码通过滑动窗口算法高效地解决了问题,时间复杂度为
O(n)
,空间复杂度为O(1)
。 - 代码逻辑清晰,适合处理较长的字符串输入。
- 通过记录字母的索引,能够快速调整窗口的左边界,确保窗口内最多只有一个字母。
五、C/C++算法源码:
代码详细注释与讲解
以下是代码的逐行注释和逻辑讲解:
1. 宏定义与结构体定义
#define MAX(a,b) ((a) > (b) ? (a) : (b)) // 定义宏 MAX,用于求两个数的最大值
typedef struct ListNode {
int ele; // 链表节点的值
struct ListNode* next; // 指向下一个节点的指针
} ListNode;
typedef struct {
int size; // 链表的大小
ListNode* head; // 链表的头节点
ListNode* tail; // 链表的尾节点
} LinkedList;
- 功能:
- 定义了一个宏
MAX
,用于求两个数的最大值。 - 定义了链表节点
ListNode
和链表LinkedList
的结构体。
- 定义了一个宏
- 关键点:
ListNode
:包含一个整数值ele
和一个指向下一个节点的指针next
。LinkedList
:包含链表的大小size
,以及指向头节点和尾节点的指针head
和tail
。
2. 链表操作函数
LinkedList* new_LinkedList() {
LinkedList* link = (LinkedList*) malloc(sizeof(LinkedList)); // 分配内存
link->size = 0; // 初始化链表大小为 0
link->head = NULL; // 初始化头节点为 NULL
link->tail = NULL; // 初始化尾节点为 NULL
return link; // 返回新创建的链表
}
void addLast_LinkedList(LinkedList* link, int ele) {
ListNode* node = (ListNode*) malloc(sizeof(ListNode)); // 分配内存
node->ele = ele; // 设置节点的值
node->next = NULL; // 设置节点的下一个指针为 NULL
if (link->size == 0) { // 如果链表为空
link->head = node; // 设置头节点为新节点
link->tail = node; // 设置尾节点为新节点
} else { // 如果链表不为空
link->tail->next = node; // 将新节点添加到链表尾部
link->tail = node; // 更新尾节点
}
link->size++; // 链表大小加 1
}
int removeFirst_LinkedList(LinkedList* link) {
if (link->size == 0) exit(-1); // 如果链表为空,退出程序
ListNode* removed = link->head; // 获取头节点
if (link->size == 1) { // 如果链表只有一个节点
link->head = NULL; // 设置头节点为 NULL
link->tail = NULL; // 设置尾节点为 NULL
} else { // 如果链表有多个节点
link->head = link->head->next; // 更新头节点为下一个节点
}
link->size--; // 链表大小减 1
int res = removed->ele; // 获取被移除节点的值
free(removed); // 释放被移除节点的内存
return res; // 返回被移除节点的值
}
- 功能:
new_LinkedList
:创建一个新的空链表。addLast_LinkedList
:在链表尾部添加一个新节点。removeFirst_LinkedList
:移除链表的头节点并返回其值。
- 关键点:
new_LinkedList
:初始化链表的大小、头节点和尾节点。addLast_LinkedList
:将新节点添加到链表尾部,并更新链表的大小和尾节点。removeFirst_LinkedList
:移除链表的头节点,并更新链表的大小和头节点。
3. 主函数 main
int main() {
char s[100000]; // 定义字符数组,用于存储输入字符串
gets(s); // 从控制台读取输入字符串
int maxLen = -1; // 记录满足条件的最长子串长度,初始值为 -1
int hasLetter = 0; // 标记字符串中是否至少有一个字母
int l = 0; // 滑动窗口的左指针,初始值为 0
int r = 0; // 滑动窗口的右指针,初始值为 0
LinkedList* letterIdx = new_LinkedList(); // 创建一个链表,用于记录字母的索引
int len = strlen(s); // 获取输入字符串的长度
while (r < len) { // 遍历字符串
char c = s[r]; // 获取当前字符
if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) { // 如果当前字符是字母
hasLetter = 1; // 标记字符串中有字母
addLast_LinkedList(letterIdx, r); // 将当前字母的索引加入链表
if (letterIdx->size > 1) { // 如果链表中有超过一个字母的索引
l = removeFirst_LinkedList(letterIdx) + 1; // 移动左指针到第一个字母的下一个位置
}
if (r == l) { // 如果左右指针重合
r++; // 移动右指针
continue; // 跳过后续逻辑
}
}
maxLen = MAX(maxLen, r - l + 1); // 更新最大长度
r++; // 移动右指针
}
if (!hasLetter) { // 如果字符串中没有字母
puts("-1"); // 输出 -1
} else { // 如果字符串中有字母
printf("%d\n", maxLen); // 输出满足条件的最长子串长度
}
return 0;
}
- 功能:通过滑动窗口算法找到满足条件的最长子串长度。
- 关键点:
- 输入处理:
- 使用
gets(s)
从控制台读取输入字符串。
- 使用
- 滑动窗口逻辑:
- 使用两个指针
l
和r
表示窗口的左右边界。 - 使用链表
letterIdx
记录字母的索引。 - 如果窗口中有超过一个字母,则移动左指针
l
到第一个字母的下一个位置。 - 更新满足条件的最长子串长度
maxLen
。
- 使用两个指针
- 边界条件处理:
- 如果字符串中没有字母,则输出
-1
。 - 否则输出满足条件的最长子串长度。
- 如果字符串中没有字母,则输出
- 输入处理:
代码逻辑总结
-
滑动窗口初始化:
- 使用两个指针
l
和r
表示窗口的左右边界。 - 使用链表
letterIdx
记录字母的索引。
- 使用两个指针
-
窗口扩展:
- 右指针
r
不断向右移动,扩展窗口。 - 如果遇到字母,则记录其索引,并检查窗口中是否已经有超过一个字母。
- 右指针
-
窗口收缩:
- 如果窗口中有超过一个字母,则移动左指针
l
到第一个字母的下一个位置。
- 如果窗口中有超过一个字母,则移动左指针
-
更新结果:
- 每次窗口扩展或收缩后,更新满足条件的最长子串长度
maxLen
。
- 每次窗口扩展或收缩后,更新满足条件的最长子串长度
-
边界条件:
- 如果字符串中没有字母,则输出
-1
。
- 如果字符串中没有字母,则输出
示例运行
输入 1:
abC124ACb
输出 1:
4
输入 2:
a5
输出 2:
2
输入 3:
aBB9
输出 3:
2
输入 4:
abcdef
输出 4:
-1
总结
- 这段代码通过滑动窗口算法高效地解决了问题,时间复杂度为
O(n)
,空间复杂度为O(1)
。 - 代码逻辑清晰,适合处理较长的字符串输入。
- 通过链表记录字母的索引,能够快速调整窗口的左边界,确保窗口内最多只有一个字母。
六、尾言
什么是华为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 或监考人员进行反馈。
祝你考试顺利,取得理想成绩!
原文地址:https://blog.csdn.net/m0_63168877/article/details/145249495
免责声明:本站文章内容转载自网络资源,如侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!