自学内容网 自学内容网

【2024年华为OD机试】(C卷,100分)- 求满足条件的最长子串的长度 (Java & JS & Python&C/C++)

在这里插入图片描述

一、问题描述

题目解析

我们需要找到一个字符串中最长的子串,该子串满足以下条件:

  1. 子串中只能包含一个字母(a~zA~Z),其余字符必须是数字。
  2. 字母可以在子串中的任意位置。

如果字符串中没有满足条件的子串(例如全是字母或全是数字),则返回 -1

解题思路

我们可以使用滑动窗口的方法来解决这个问题。滑动窗口的核心思想是维护一个窗口(即子串),通过移动窗口的左右边界来找到满足条件的最长子串。

具体步骤:
  1. 初始化

    • 使用两个指针 leftright 来表示滑动窗口的左右边界。
    • 使用一个变量 letterCount 来记录当前窗口中字母的数量。
    • 使用一个变量 maxLen 来记录满足条件的最长子串的长度。
    • 使用一个变量 lastLetterIndex 来记录窗口中最后一个字母的位置。
  2. 滑动窗口

    • 遍历字符串,移动 right 指针。
    • 如果当前字符是字母,则 letterCount 加 1,并更新 lastLetterIndex
    • 如果 letterCount 超过 1(即窗口中有超过一个字母),则需要移动 left 指针:
      • 如果 left 指向的是字母,则移动 leftlastLetterIndex + 1,并减少 letterCount
      • 如果 left 指向的是数字,则直接移动 leftlastLetterIndex + 1
    • 更新 maxLen 为当前窗口的长度和 maxLen 中的较大值。
  3. 返回结果

    • 如果 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;
}

代码讲解

  1. 滑动窗口的核心逻辑

    • 使用 leftright 指针表示窗口的左右边界。
    • right 指针遇到字母时,增加 letterCount 并记录字母的位置。
    • 如果 letterCount 超过 1,则移动 left 指针到最后一个字母的下一个位置,并减少 letterCount
  2. 边界条件处理

    • 如果字符串中没有字母或全是字母,则返回 -1
    • 如果字符串中只有一个字母,则整个字符串就是满足条件的子串。
  3. 时间复杂度

    • 由于 leftright 指针最多各遍历一次字符串,时间复杂度为 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
  • lr:滑动窗口的左右指针,初始值均为 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++; // 移动右指针
}
  • 字母处理
    • 如果当前字符是字母,则标记 hasLettertrue,并将字母的索引存入 letterIdx
    • 如果 letterIdx 的长度超过 1(即窗口中有超过一个字母),则移动左指针 l 到第一个字母的下一个位置。
  • 更新最大长度
    • 每次右指针 r 移动后,计算当前窗口的长度 r - l + 1,并更新 maxLen
  • 右指针移动
    • 右指针 r 每次循环都会向右移动。

4. 边界条件处理

if (!hasLetter) return -1;
return maxLen;
  • 如果字符串中没有字母(即 hasLetterfalse),则返回 -1
  • 否则返回 maxLen

5. 辅助函数

function isLetter(c) {
  return (c >= "a" && c <= "z") || (c >= "A" && c <= "Z");
}
  • 判断一个字符是否是字母(a~zA~Z)。

6. 代码逻辑总结

  1. 滑动窗口初始化

    • 使用两个指针 lr 表示窗口的左右边界。
    • 使用 letterIdx 记录字母的索引,方便在窗口中有多个字母时调整左指针。
  2. 窗口扩展

    • 右指针 r 不断向右移动,扩展窗口。
    • 如果遇到字母,则记录其索引,并检查窗口中是否已经有超过一个字母。
  3. 窗口收缩

    • 如果窗口中有超过一个字母,则移动左指针 l 到第一个字母的下一个位置。
  4. 更新结果

    • 每次窗口扩展或收缩后,更新满足条件的最长子串长度 maxLen
  5. 边界条件

    • 如果字符串中没有字母,则返回 -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:用于标记字符串中是否至少有一个字母。
    • lr:滑动窗口的左右指针,初始值均为 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++; // 移动右指针
}
  • 功能:通过滑动窗口遍历字符串,找到满足条件的最长子串。
  • 关键点
    • 字母处理
      • 如果当前字符是字母,则标记 hasLettertrue,并将字母的索引加入 letterIdx
      • 如果 letterIdx 的大小超过 1(即窗口中有超过一个字母),则移动左指针 l 到第一个字母的下一个位置。
    • 窗口扩展
      • 右指针 r 不断向右移动,扩展窗口。
    • 窗口收缩
      • 如果窗口中有超过一个字母,则移动左指针 l 到第一个字母的下一个位置。
    • 更新最大长度
      • 每次窗口扩展或收缩后,计算当前窗口的长度 r - l + 1,并更新 maxLen

4. 边界条件处理
if (!hasLetter) return -1; // 如果字符串中没有字母,返回 -1
return maxLen; // 返回满足条件的最长子串长度
  • 功能:处理字符串中没有字母的情况。
  • 关键点
    • 如果 hasLetterfalse(即字符串中没有字母),则返回 -1
    • 否则返回 maxLen

5. 辅助方法 isLetter
public static boolean isLetter(char c) {
  return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); // 判断字符是否是字母
}
  • 功能:判断一个字符是否是字母(a~zA~Z)。
  • 关键点
    • 使用字符的 ASCII 值范围判断是否是字母。

代码逻辑总结

  1. 滑动窗口初始化

    • 使用两个指针 lr 表示窗口的左右边界。
    • 使用 letterIdx 记录字母的索引,方便在窗口中有多个字母时调整左指针。
  2. 窗口扩展

    • 右指针 r 不断向右移动,扩展窗口。
    • 如果遇到字母,则记录其索引,并检查窗口中是否已经有超过一个字母。
  3. 窗口收缩

    • 如果窗口中有超过一个字母,则移动左指针 l 到第一个字母的下一个位置。
  4. 更新结果

    • 每次窗口扩展或收缩后,更新满足条件的最长子串长度 maxLen
  5. 边界条件

    • 如果字符串中没有字母,则返回 -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
    • lr:滑动窗口的左右指针,初始值均为 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  # 移动右指针
  • 功能:通过滑动窗口遍历字符串,找到满足条件的最长子串。
  • 关键点
    • 字母处理
      • 如果当前字符是字母,则标记 hasLetterTrue,并将字母的索引加入 letterIdx
      • 如果 letterIdx 的长度超过 1(即窗口中有超过一个字母),则移动左指针 l 到第一个字母的下一个位置。
    • 窗口扩展
      • 右指针 r 不断向右移动,扩展窗口。
    • 窗口收缩
      • 如果窗口中有超过一个字母,则移动左指针 l 到第一个字母的下一个位置。
    • 更新最大长度
      • 每次窗口扩展或收缩后,计算当前窗口的长度 r - l + 1,并更新 maxLen

4. 边界条件处理
if not hasLetter:  # 如果字符串中没有字母
    return -1  # 返回 -1
return maxLen  # 返回满足条件的最长子串长度
  • 功能:处理字符串中没有字母的情况。
  • 关键点
    • 如果 hasLetterFalse(即字符串中没有字母),则返回 -1
    • 否则返回 maxLen

5. 算法调用
print(getResult())  # 调用 getResult 方法并输出结果
  • 功能:调用 getResult 方法并输出结果。
  • 关键点
    • print(getResult()):调用 getResult 方法并输出结果。

代码逻辑总结

  1. 滑动窗口初始化

    • 使用两个指针 lr 表示窗口的左右边界。
    • 使用 letterIdx 记录字母的索引,方便在窗口中有多个字母时调整左指针。
  2. 窗口扩展

    • 右指针 r 不断向右移动,扩展窗口。
    • 如果遇到字母,则记录其索引,并检查窗口中是否已经有超过一个字母。
  3. 窗口收缩

    • 如果窗口中有超过一个字母,则移动左指针 l 到第一个字母的下一个位置。
  4. 更新结果

    • 每次窗口扩展或收缩后,更新满足条件的最长子串长度 maxLen
  5. 边界条件

    • 如果字符串中没有字母,则返回 -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,以及指向头节点和尾节点的指针 headtail

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) 从控制台读取输入字符串。
    • 滑动窗口逻辑
      • 使用两个指针 lr 表示窗口的左右边界。
      • 使用链表 letterIdx 记录字母的索引。
      • 如果窗口中有超过一个字母,则移动左指针 l 到第一个字母的下一个位置。
      • 更新满足条件的最长子串长度 maxLen
    • 边界条件处理
      • 如果字符串中没有字母,则输出 -1
      • 否则输出满足条件的最长子串长度。

代码逻辑总结

  1. 滑动窗口初始化

    • 使用两个指针 lr 表示窗口的左右边界。
    • 使用链表 letterIdx 记录字母的索引。
  2. 窗口扩展

    • 右指针 r 不断向右移动,扩展窗口。
    • 如果遇到字母,则记录其索引,并检查窗口中是否已经有超过一个字母。
  3. 窗口收缩

    • 如果窗口中有超过一个字母,则移动左指针 l 到第一个字母的下一个位置。
  4. 更新结果

    • 每次窗口扩展或收缩后,更新满足条件的最长子串长度 maxLen
  5. 边界条件

    • 如果字符串中没有字母,则输出 -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,外包开发工程师)是华为针对软件开发工程师岗位的一种招聘形式,主要包括笔试、技术面试以及综合面试等环节。尤其在笔试部分,算法题的机试至关重要。

为什么刷题很重要?

  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 或监考人员进行反馈。

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


原文地址:https://blog.csdn.net/m0_63168877/article/details/145249495

免责声明:本站文章内容转载自网络资源,如侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!