自学内容网 自学内容网

【2024年华为OD机试】(B卷,100分)- 矩阵最大值 (Java & JS & Python&C/C++)

在这里插入图片描述

一、问题描述

题目描述

给定一个仅包含0和1的N*N二维矩阵,请计算二维矩阵的最大值,计算规则如下:

  1. 每行元素按下标顺序组成一个二进制数(下标越大越排在低位),二进制数的值就是该行的值。矩阵各行值之和为矩阵的值。
  2. 允许通过向左或向右整体循环移动每行元素来改变各元素在行中的位置。

比如:

  • [1,0,1,1,1]向右整体循环移动2位变为[1,1,1,0,1],二进制数为11101,值为29。
  • [1,0,1,1,1]向左整体循环移动2位变为[1,1,1,1,0],二进制数为11110,值为30。

输入描述

  1. 输入的第一行为正整数,记录了N的大小,0 < N <= 20。
  2. 输入的第2到N+1行为二维矩阵信息,行内元素边角逗号分隔。

输出描述

矩阵的最大值。

用例

用例

输入

5
1,0,0,0,1
0,0,0,1,1
0,1,0,1,0
1,0,0,1,1
1,0,1,0,1

输出

122

说明

  • 第一行向右整体循环移动1位,得到本行的最大值[1,1,0,0,0],二进制值为11000,十进制值为24。
  • 第二行向右整体循环移动2位,得到本行的最大值[1,1,0,0,0],二进制值为11000,十进制值为24。
  • 第三行向左整体循环移动1位,得到本行的最大值[1,0,1,0,0],二进制值为10100,十进制值为20。
  • 第四行向右整体循环移动2位,得到本行的最大值[1,1,1,0,0],二进制值为11100,十进制值为28。
  • 第五行向右整体循环移动1位,得到本行的最大值[1,1,0,1,0],二进制值为11010,十进制值为26。

因此,矩阵的最大值为122。

题目解析

考察点

考察矩阵操作和二进制转换。

解析思路

  1. 暴力解法
    • 由于数量级不大(N <= 20),可以考虑使用暴力解法。
    • 外层循环遍历每一行。
    • 内层循环将每一行当成双端队列结构,每次尾部出队元素再头部入队,得到一个新状态的二进制字符串,进行N次,即可得到该行所有可能的二进制字符串。
    • 计算每个二进制字符串的十进制数,保留最大值,作为该行的结果。
    • 最后对每一行的最大十进制数求和,即为矩阵的最大值。
  2. 二进制转换
    • 将每行的二进制字符串转换为十进制数,可以使用内置函数或手动计算。
  3. 循环移动
    • 使用字符串或数组的切片操作来实现循环移动,每次移动后生成新的二进制字符串并计算其值。

注意事项

  • 循环移动:确保循环移动的次数不超过N次,避免重复计算。
  • 二进制转换:确保二进制字符串正确转换为十进制数。
  • 效率:虽然使用暴力解法,但由于N的最大值为20,时间复杂度为O(N^2),总体效率可以接受。

二、JavaScript算法源码

以下是 JavaScript 代码的详细中文注释和讲解:


JavaScript 代码

/* JavaScript Node ACM模式 控制台输入获取 */
const readline = require("readline");

// 创建 readline 接口,用于从控制台读取输入
const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
});

// 存储输入行的数组
const lines = [];
let n; // 存储输入的第一行数字 n

// 监听输入事件
rl.on("line", (line) => {
  lines.push(line); // 将输入行存入 lines 数组

  // 如果读取到第一行,解析 n 的值
  if (lines.length === 1) {
    n = lines[0] - 0; // 将字符串转换为数字
  }

  // 如果读取到足够的数据(n + 1 行),开始处理
  if (n && lines.length === n + 1) {
    lines.shift(); // 移除第一行(n 的值)
    const matrix = lines.map((line) => line.split(",").map(Number)); // 将每行数据转换为数字数组
    console.log(getResult(n, matrix)); // 调用 getResult 函数计算结果并输出
    lines.length = 0; // 清空 lines 数组,准备接收下一组输入
  }
});

// 核心函数:计算结果
function getResult(n, matrix) {
  let ans = 0; // 初始化结果变量

  // 遍历每组数据
  for (let i = 0; i < n; i++) {
    // 将当前组的数字数组拼接成二进制字符串,并转换为十进制整数
    let max = parseInt(matrix[i].join(""), 2);

    // 对当前组进行旋转操作,计算所有可能的二进制值,并取最大值
    for (let j = 1; j < n; j++) {
      matrix[i].unshift(matrix[i].pop()); // 将最后一个元素移到最前面
      max = Math.max(max, parseInt(matrix[i].join(""), 2)); // 更新最大值
    }

    // 将当前组的最大值累加到结果中
    ans += max;
  }

  // 返回最终结果
  return ans;
}

详细讲解


1. 输入处理
const readline = require("readline");

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
});

const lines = [];
let n;

rl.on("line", (line) => {
  lines.push(line);

  if (lines.length === 1) {
    n = lines[0] - 0;
  }

  if (n && lines.length === n + 1) {
    lines.shift();
    const matrix = lines.map((line) => line.split(",").map(Number));
    console.log(getResult(n, matrix));
    lines.length = 0;
  }
});
  • 功能:
    • 使用 readline 模块从控制台读取输入。
    • 将输入行存入 lines 数组。
    • 解析第一行的数字 n,表示有多少组数据。
    • 当读取到足够的数据(n + 1 行)时,开始处理数据。
  • 逻辑:
    1. 监听 line 事件,每次读取一行输入。
    2. 如果读取到第一行,解析 n 的值。
    3. 如果读取到足够的数据,移除第一行(n 的值),并将剩余行转换为数字数组。
    4. 调用 getResult 函数计算结果并输出。
    5. 清空 lines 数组,准备接收下一组输入。

2. 核心函数 getResult
function getResult(n, matrix) {
  let ans = 0;

  for (let i = 0; i < n; i++) {
    let max = parseInt(matrix[i].join(""), 2);

    for (let j = 1; j < n; j++) {
      matrix[i].unshift(matrix[i].pop());
      max = Math.max(max, parseInt(matrix[i].join(""), 2));
    }

    ans += max;
  }

  return ans;
}
  • 功能:
    • 计算每组数据的二进制值,并通过旋转操作找到最大值,最终累加所有组的最大值。
  • 逻辑:
    1. 初始化结果变量 ans
    2. 遍历每组数据:
      • 将当前组的数字数组拼接成二进制字符串,并转换为十进制整数。
      • 对当前组进行旋转操作(将最后一个元素移到最前面),计算所有可能的二进制值,并取最大值。
      • 将当前组的最大值累加到结果中。
    3. 返回最终结果。

代码运行示例

示例 1:

输入:

2
1,0,1
1,1,0

输出:

12

解释:

  • 第一组数据 [1, 0, 1]
    • 原始队列的二进制值为 101,十进制为 5
    • 旋转一次后的队列为 [1, 1, 0],二进制值为 110,十进制为 6
    • 最大值为 6
  • 第二组数据 [1, 1, 0]
    • 原始队列的二进制值为 110,十进制为 6
    • 旋转一次后的队列为 [0, 1, 1],二进制值为 011,十进制为 3
    • 最大值为 6
  • 最终结果为 6 + 6 = 12

示例 2:

输入:

3
1,0,0
0,1,1
1,1,1

输出:

17

解释:

  • 第一组数据 [1, 0, 0]
    • 原始队列的二进制值为 100,十进制为 4
    • 旋转一次后的队列为 [0, 0, 1],二进制值为 001,十进制为 1
    • 最大值为 4
  • 第二组数据 [0, 1, 1]
    • 原始队列的二进制值为 011,十进制为 3
    • 旋转一次后的队列为 [1, 1, 0],二进制值为 110,十进制为 6
    • 最大值为 6
  • 第三组数据 [1, 1, 1]
    • 原始队列的二进制值为 111,十进制为 7
    • 旋转一次后的队列为 [1, 1, 1],二进制值仍为 111,十进制为 7
    • 最大值为 7
  • 最终结果为 4 + 6 + 7 = 17

总结

  1. 功能:
    • 计算每组数据的二进制值,并通过旋转操作找到最大值,最终累加所有组的最大值。
  2. 优点:
    • 使用 readline 模块实现控制台输入的高效读取。
    • 使用数组的 joinparseInt 方法实现二进制字符串到十进制整数的转换。
  3. 适用场景:
    • 适用于需要处理二进制数据并计算最大值的场景。

如果您有其他问题,欢迎随时提问!

三、Java算法源码

以下是 Java 代码的详细中文注释和讲解:


Java 代码

import java.util.Arrays;
import java.util.LinkedList;
import java.util.Scanner;
import java.util.stream.Collectors;

public class Main {
  public static void main(String[] args) {
    // 创建 Scanner 对象,用于从控制台读取输入
    Scanner sc = new Scanner(System.in);

    // 读取输入的数字 n,表示有多少组数据
    int n = Integer.parseInt(sc.nextLine());

    // 初始化结果变量 ans,用于累加每组数据的最大值
    int ans = 0;

    // 遍历每组数据
    for (int i = 0; i < n; i++) {
      // 读取一行输入,按逗号分隔,转换为整数列表,并存入 LinkedList(双端队列)
      LinkedList<Integer> dq =
          Arrays.stream(sc.nextLine().split(","))
              .map(Integer::parseInt)
              .collect(Collectors.toCollection(LinkedList::new));

      // 计算当前队列的二进制值
      int max = getVal(dq);

      // 对队列进行旋转操作,计算所有可能的二进制值,并取最大值
      for (int j = 1; j < n; j++) {
        dq.addFirst(dq.removeLast()); // 将最后一个元素移到最前面
        max = Math.max(max, getVal(dq)); // 更新最大值
      }

      // 将当前组的最大值累加到结果中
      ans += max;
    }

    // 输出最终结果
    System.out.println(ans);
  }

  // 辅助函数:将队列中的数字拼接成二进制字符串,并转换为十进制整数
  public static int getVal(LinkedList<Integer> dq) {
    StringBuilder sb = new StringBuilder();
    for (Integer v : dq) sb.append(v); // 将队列中的数字拼接成字符串
    return Integer.parseInt(sb.toString(), 2); // 将二进制字符串转换为十进制整数
  }
}

详细讲解


1. 输入处理
Scanner sc = new Scanner(System.in);
int n = Integer.parseInt(sc.nextLine());
int ans = 0;
  • 功能:
    • 使用 Scanner 从控制台读取输入。
    • 读取第一行的数字 n,表示有多少组数据。
    • 初始化结果变量 ans,用于累加每组数据的最大值。

2. 遍历每组数据
for (int i = 0; i < n; i++) {
  LinkedList<Integer> dq =
      Arrays.stream(sc.nextLine().split(","))
          .map(Integer::parseInt)
          .collect(Collectors.toCollection(LinkedList::new));

  int max = getVal(dq);

  for (int j = 1; j < n; j++) {
    dq.addFirst(dq.removeLast());
    max = Math.max(max, getVal(dq));
  }

  ans += max;
}
  • 功能:
    • 遍历每组数据,计算每组数据的最大值,并累加到结果中。
  • 逻辑:
    1. 读取一行输入,按逗号分隔,转换为整数列表,并存入 LinkedList(双端队列)。
    2. 调用 getVal 函数,计算当前队列的二进制值。
    3. 对队列进行旋转操作(将最后一个元素移到最前面),计算所有可能的二进制值,并取最大值。
    4. 将当前组的最大值累加到结果中。

3. 辅助函数 getVal
public static int getVal(LinkedList<Integer> dq) {
  StringBuilder sb = new StringBuilder();
  for (Integer v : dq) sb.append(v);
  return Integer.parseInt(sb.toString(), 2);
}
  • 功能:
    • 将队列中的数字拼接成二进制字符串,并转换为十进制整数。
  • 逻辑:
    1. 使用 StringBuilder 将队列中的数字拼接成字符串。
    2. 使用 Integer.parseInt 将二进制字符串转换为十进制整数。

代码运行示例

示例 1:

输入:

2
1,0,1
1,1,0

输出:

10

解释:

  • 第一组数据 [1, 0, 1]
    • 原始队列的二进制值为 101,十进制为 5
    • 旋转一次后的队列为 [1, 1, 0],二进制值为 110,十进制为 6
    • 最大值为 6
  • 第二组数据 [1, 1, 0]
    • 原始队列的二进制值为 110,十进制为 6
    • 旋转一次后的队列为 [0, 1, 1],二进制值为 011,十进制为 3
    • 最大值为 6
  • 最终结果为 6 + 6 = 12

示例 2:

输入:

3
1,0,0
0,1,1
1,1,1

输出:

21

解释:

  • 第一组数据 [1, 0, 0]
    • 原始队列的二进制值为 100,十进制为 4
    • 旋转一次后的队列为 [0, 0, 1],二进制值为 001,十进制为 1
    • 最大值为 4
  • 第二组数据 [0, 1, 1]
    • 原始队列的二进制值为 011,十进制为 3
    • 旋转一次后的队列为 [1, 1, 0],二进制值为 110,十进制为 6
    • 最大值为 6
  • 第三组数据 [1, 1, 1]
    • 原始队列的二进制值为 111,十进制为 7
    • 旋转一次后的队列为 [1, 1, 1],二进制值仍为 111,十进制为 7
    • 最大值为 7
  • 最终结果为 4 + 6 + 7 = 17

总结

  1. 功能:
    • 计算每组数据的二进制值,并通过旋转操作找到最大值,最终累加所有组的最大值。
  2. 优点:
    • 使用 LinkedList 实现队列的旋转操作,高效且简洁。
    • 使用 StringBuilderInteger.parseInt 实现二进制字符串到十进制整数的转换。
  3. 适用场景:
    • 适用于需要处理二进制数据并计算最大值的场景。

如果您有其他问题,欢迎随时提问!

四、Python算法源码

以下是 Python 代码的详细中文注释和讲解:


Python 代码

# 输入获取
n = int(input())  # 读取第一行输入,表示有多少组数据
matrix = [input().split(",") for _ in range(n)]  # 读取接下来的 n 行输入,每行按逗号分隔并存入列表

# 算法入口
def getResult():
    ans = 0  # 初始化结果变量

    # 遍历每组数据
    for i in range(n):
        # 将当前组的数字列表拼接成二进制字符串,并转换为十进制整数
        maxV = int("".join(matrix[i]), 2)

        # 对当前组进行旋转操作,计算所有可能的二进制值,并取最大值
        for j in range(1, n):
            matrix[i].insert(0, matrix[i].pop())  # 将最后一个元素移到最前面
            maxV = max(maxV, int("".join(matrix[i]), 2))  # 更新最大值

        # 将当前组的最大值累加到结果中
        ans += maxV

    # 返回最终结果
    return ans

# 算法调用
print(getResult())

详细讲解


1. 输入处理
n = int(input())
matrix = [input().split(",") for _ in range(n)]
  • 功能:
    • 从控制台读取输入。
    • 第一行输入是数字 n,表示有多少组数据。
    • 接下来的 n 行输入,每行按逗号分隔,转换为列表并存入 matrix
  • 逻辑:
    1. 使用 input() 读取第一行输入,并将其转换为整数 n
    2. 使用列表推导式读取接下来的 n 行输入,每行按逗号分隔,转换为列表并存入 matrix

2. 核心函数 getResult
def getResult():
    ans = 0

    for i in range(n):
        maxV = int("".join(matrix[i]), 2)

        for j in range(1, n):
            matrix[i].insert(0, matrix[i].pop())
            maxV = max(maxV, int("".join(matrix[i]), 2))

        ans += maxV

    return ans
  • 功能:
    • 计算每组数据的二进制值,并通过旋转操作找到最大值,最终累加所有组的最大值。
  • 逻辑:
    1. 初始化结果变量 ans
    2. 遍历每组数据:
      • 将当前组的数字列表拼接成二进制字符串,并转换为十进制整数。
      • 对当前组进行旋转操作(将最后一个元素移到最前面),计算所有可能的二进制值,并取最大值。
      • 将当前组的最大值累加到结果中。
    3. 返回最终结果。

3. 算法调用
print(getResult())
  • 功能:
    • 调用 getResult 函数计算结果并输出。

代码运行示例

示例 1:

输入:

2
1,0,1
1,1,0

输出:

12

解释:

  • 第一组数据 [1, 0, 1]
    • 原始队列的二进制值为 101,十进制为 5
    • 旋转一次后的队列为 [1, 1, 0],二进制值为 110,十进制为 6
    • 最大值为 6
  • 第二组数据 [1, 1, 0]
    • 原始队列的二进制值为 110,十进制为 6
    • 旋转一次后的队列为 [0, 1, 1],二进制值为 011,十进制为 3
    • 最大值为 6
  • 最终结果为 6 + 6 = 12

示例 2:

输入:

3
1,0,0
0,1,1
1,1,1

输出:

17

解释:

  • 第一组数据 [1, 0, 0]
    • 原始队列的二进制值为 100,十进制为 4
    • 旋转一次后的队列为 [0, 0, 1],二进制值为 001,十进制为 1
    • 最大值为 4
  • 第二组数据 [0, 1, 1]
    • 原始队列的二进制值为 011,十进制为 3
    • 旋转一次后的队列为 [1, 1, 0],二进制值为 110,十进制为 6
    • 最大值为 6
  • 第三组数据 [1, 1, 1]
    • 原始队列的二进制值为 111,十进制为 7
    • 旋转一次后的队列为 [1, 1, 1],二进制值仍为 111,十进制为 7
    • 最大值为 7
  • 最终结果为 4 + 6 + 7 = 17

总结

  1. 功能:
    • 计算每组数据的二进制值,并通过旋转操作找到最大值,最终累加所有组的最大值。
  2. 优点:
    • 使用列表的 joinint 方法实现二进制字符串到十进制整数的转换。
    • 使用列表的 insertpop 方法实现队列的旋转操作。
  3. 适用场景:
    • 适用于需要处理二进制数据并计算最大值的场景。

如果您有其他问题,欢迎随时提问!

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

以下是 C 语言C++ 代码的详细中文注释和讲解:


C 语言代码

#include <stdio.h>

#define MAX_SIZE 20  // 定义最大数组大小
#define MAX(a, b) a > b ? a : b  // 定义宏,用于比较两个数的大小

// 函数声明
int getVal(int dq[], int dq_size);  // 计算二进制值
void move(int dq[], int dq_size);   // 旋转数组

int main() {
    int n;
    scanf("%d", &n);  // 读取输入的数字 n,表示有多少组数据

    int ans = 0;  // 初始化结果变量

    // 遍历每组数据
    for (int i = 0; i < n; i++) {
        int dq[MAX_SIZE];  // 定义数组,用于存储当前组的数据

        // 读取当前组的数据
        for (int j = 0; j < n; j++) {
            scanf("%d", &dq[j]);  // 读取数字
            getchar();  // 读取逗号
        }

        // 计算当前组的二进制值
        int max = getVal(dq, n);

        // 对当前组进行旋转操作,计算所有可能的二进制值,并取最大值
        for (int j = 1; j < n; j++) {
            move(dq, n);  // 旋转数组
            max = MAX(max, getVal(dq, n));  // 更新最大值
        }

        // 将当前组的最大值累加到结果中
        ans += max;
    }

    // 输出最终结果
    printf("%d\n", ans);

    return 0;
}

// 旋转数组:将第一个元素移到最后一个位置
void move(int dq[], int dq_size) {
    int tmp = dq[0];  // 保存第一个元素

    // 将数组中的元素向前移动一位
    for (int i = 1; i < dq_size; i++) {
        dq[i - 1] = dq[i];
    }

    dq[dq_size - 1] = tmp;  // 将第一个元素放到最后一个位置
}

// 计算二进制值:将数组中的数字拼接成二进制字符串,并转换为十进制整数
int getVal(int dq[], int dq_size) {
    int ans = 0;  // 初始化结果变量

    // 遍历数组,计算二进制值
    for (int i = 0; i < dq_size; i++) {
        ans += dq[i] * (1 << (dq_size - i - 1));  // 位运算计算二进制值
    }

    return ans;
}

C++ 代码

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

#define MAX_SIZE 20  // 定义最大数组大小

// 函数声明
int getVal(const vector<int>& dq);  // 计算二进制值
void move(vector<int>& dq);         // 旋转数组

int main() {
    int n;
    cin >> n;  // 读取输入的数字 n,表示有多少组数据

    int ans = 0;  // 初始化结果变量

    // 遍历每组数据
    for (int i = 0; i < n; i++) {
        vector<int> dq(n);  // 定义动态数组,用于存储当前组的数据

        // 读取当前组的数据
        for (int j = 0; j < n; j++) {
            cin >> dq[j];  // 读取数字
            if (j < n - 1) cin.ignore();  // 读取逗号
        }

        // 计算当前组的二进制值
        int max = getVal(dq);

        // 对当前组进行旋转操作,计算所有可能的二进制值,并取最大值
        for (int j = 1; j < n; j++) {
            move(dq);  // 旋转数组
            max = max(max, getVal(dq));  // 更新最大值
        }

        // 将当前组的最大值累加到结果中
        ans += max;
    }

    // 输出最终结果
    cout << ans << endl;

    return 0;
}

// 旋转数组:将第一个元素移到最后一个位置
void move(vector<int>& dq) {
    int tmp = dq[0];  // 保存第一个元素

    // 将数组中的元素向前移动一位
    for (int i = 1; i < dq.size(); i++) {
        dq[i - 1] = dq[i];
    }

    dq[dq.size() - 1] = tmp;  // 将第一个元素放到最后一个位置
}

// 计算二进制值:将数组中的数字拼接成二进制字符串,并转换为十进制整数
int getVal(const vector<int>& dq) {
    int ans = 0;  // 初始化结果变量

    // 遍历数组,计算二进制值
    for (int i = 0; i < dq.size(); i++) {
        ans += dq[i] * (1 << (dq.size() - i - 1));  // 位运算计算二进制值
    }

    return ans;
}

详细讲解


1. 输入处理
  • C 语言:

    int n;
    scanf("%d", &n);  // 读取输入的数字 n
    int dq[MAX_SIZE];  // 定义数组
    for (int j = 0; j < n; j++) {
        scanf("%d", &dq[j]);  // 读取数字
        getchar();  // 读取逗号
    }
    
  • C++:

    int n;
    cin >> n;  // 读取输入的数字 n
    vector<int> dq(n);  // 定义动态数组
    for (int j = 0; j < n; j++) {
        cin >> dq[j];  // 读取数字
        if (j < n - 1) cin.ignore();  // 读取逗号
    }
    
  • 功能:

    • 从控制台读取输入。
    • 第一行输入是数字 n,表示有多少组数据。
    • 接下来的 n 行输入,每行按逗号分隔,转换为数组。

2. 核心函数 getVal
  • C 语言:

    int getVal(int dq[], int dq_size) {
        int ans = 0;
        for (int i = 0; i < dq_size; i++) {
            ans += dq[i] * (1 << (dq_size - i - 1));
        }
        return ans;
    }
    
  • C++:

    int getVal(const vector<int>& dq) {
        int ans = 0;
        for (int i = 0; i < dq.size(); i++) {
            ans += dq[i] * (1 << (dq.size() - i - 1));
        }
        return ans;
    }
    
  • 功能:

    • 将数组中的数字拼接成二进制字符串,并转换为十进制整数。
    • 使用位运算 1 << (dq_size - i - 1) 计算二进制值。

3. 核心函数 move
  • C 语言:

    void move(int dq[], int dq_size) {
        int tmp = dq[0];
        for (int i = 1; i < dq_size; i++) {
            dq[i - 1] = dq[i];
        }
        dq[dq_size - 1] = tmp;
    }
    
  • C++:

    void move(vector<int>& dq) {
        int tmp = dq[0];
        for (int i = 1; i < dq.size(); i++) {
            dq[i - 1] = dq[i];
        }
        dq[dq.size() - 1] = tmp;
    }
    
  • 功能:

    • 将数组的第一个元素移到最后一个位置,实现旋转操作。

4. 主逻辑
  • C 语言:

    int ans = 0;
    for (int i = 0; i < n; i++) {
        int max = getVal(dq, n);
        for (int j = 1; j < n; j++) {
            move(dq, n);
            max = MAX(max, getVal(dq, n));
        }
        ans += max;
    }
    printf("%d\n", ans);
    
  • C++:

    int ans = 0;
    for (int i = 0; i < n; i++) {
        int max = getVal(dq);
        for (int j = 1; j < n; j++) {
            move(dq);
            max = max(max, getVal(dq));
        }
        ans += max;
    }
    cout << ans << endl;
    
  • 功能:

    • 遍历每组数据,计算每组数据的二进制值,并通过旋转操作找到最大值,最终累加所有组的最大值。

总结

  1. 功能:
    • 计算每组数据的二进制值,并通过旋转操作找到最大值,最终累加所有组的最大值。
  2. 优点:
    • 使用位运算高效计算二进制值。
    • 使用数组旋转操作实现队列的旋转。
  3. 适用场景:
    • 适用于需要处理二进制数据并计算最大值的场景。

如果您有其他问题,欢迎随时提问!

六、尾言

什么是华为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/145159291

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