【2024年华为OD机试】 (B卷,100分)- 字符串分割(Java JS PythonC/C++)

在这里插入图片描述

一、问题描述

题目解析

问题描述

给定一个非空字符串 s,要求将该字符串分割成若干子串,使得每个子串的 ASCII 码值之和均为“水仙花数”。具体要求如下:

  1. 若分割不成功,则返回 0
  2. 若分割成功且分割结果不唯一,则返回 -1
  3. 若分割成功且分割结果唯一,则返回分割后子串的数目。

备注

  • “水仙花数”是指一个三位数,其每位数字的立方和等于该数本身。例如,371 是水仙花数,因为 (3^3 + 7^3 + 1^3 = 371)。
  • 输入字符串的最大长度为 200

输入描述

输入一个非空字符串 s,长度不超过 200


输出描述

根据题目要求,返回以下结果之一:

  • 0:分割不成功;
  • -1:分割成功但分割结果不唯一;
  • 正整数:分割成功且分割结果唯一,返回分割后的子串数目。

题目解析

1. 水仙花数定义

水仙花数是一个三位数,其每位数字的立方和等于该数本身。例如:

  • (153 = 1^3 + 5^3 + 3^3)
  • (370 = 3^3 + 7^3 + 0^3)
  • (371 = 3^3 + 7^3 + 1^3)

2. 问题分析

  • 将字符串分割成若干子串,每个子串的 ASCII 码值之和必须为水仙花数。
  • 需要检查所有可能的分割方式,并统计满足条件的分割方式数量。
  • 根据分割方式的数量,返回相应的结果。

3. 解题思路

  1. 预处理

    • 将字符串转换为 ASCII 码值数组。
    • 计算前缀和数组,方便快速计算任意子串的 ASCII 码值之和。
  2. 递归分割

    • 从字符串的起始位置开始,尝试分割出满足条件的子串。
    • 如果当前子串的 ASCII 码值之和是水仙花数,则递归处理剩余部分。
    • 记录所有可能的分割方式及其分割的子串数目。
  3. 结果判断

    • 如果没有满足条件的分割方式,返回 0
    • 如果有多种分割方式,返回 -1
    • 如果只有一种分割方式,返回分割后的子串数目。

示例解析

示例 1

输入

abc

输出

0

说明

  • 字符串 abc 的 ASCII 码值之和为 97 + 98 + 99 = 294
  • 294 不是水仙花数,且无法分割成多个子串使其 ASCII 码值之和均为水仙花数。
  • 因此,返回 0

示例 2

输入

f3@d5a8

输出

-1

说明

  • 字符串 f3@d5a8 可以分割为以下两种方式:
    1. f3@d5a8
      • f3 的 ASCII 码值之和为 102 + 51 = 153(水仙花数)。
      • @d5a8 的 ASCII 码值之和为 64 + 100 + 53 + 97 + 56 = 370(水仙花数)。
    2. f3@d5a8
      • f3@d5 的 ASCII 码值之和为 102 + 51 + 64 + 100 + 53 = 370(水仙花数)。
      • a8 的 ASCII 码值之和为 97 + 56 = 153(水仙花数)。
  • 由于存在多种分割方式,返回 -1

示例 3

输入

AXdddF

输出

2

说明

  • 字符串 AXdddF 可以唯一分割为以下方式:
    • AX 的 ASCII 码值之和为 65 + 88 = 153(水仙花数)。
    • dddF 的 ASCII 码值之和为 100 + 100 + 100 + 70 = 370(水仙花数)。
  • 由于只有一种分割方式,返回分割后的子串数目 2

总结

  • 本题的核心是通过递归和回溯尝试所有可能的分割方式,并判断每种方式是否满足条件。
  • 使用前缀和优化可以显著提高计算效率。
  • 根据分割方式的数量,返回相应的结果。

二、JavaScript算法源码

代码详细注释与讲解

以下是对你提供的JavaScript代码的详细注释和讲解。代码的主要功能是将一个字符串分割成若干个子串,使得每个子串的ASCII码之和是一个“水仙花数”,并返回分割的次数。如果存在多种分割方式,返回-1;如果没有可行的分割方式,返回0。

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

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

// 监听输入事件,每次输入一行时触发
rl.on("line", (line) => {
  // 调用getResult函数处理输入,并输出结果
  console.log(getResult(line));
});

// 获取字符串分割结果的函数
function getResult(str) {
  // 将字符串转化为ASCII数组
  const cArr = [...str].map((ele) => ele.charCodeAt());

  // 获取字符数组的长度
  const n = cArr.length;

  // 前缀和,实现O(1)时间求解某区间内元素之和
  const preSum = new Array(n + 1).fill(0);
  for (let i = 1; i <= n; i++) preSum[i] = preSum[i - 1] + cArr[i - 1];

  // res记录成功分割的情况
  const res = [];
  // 递归分割
  recursive(preSum, n, 0, 0, res);

  // 根据res的大小返回不同的结果
  if (res.length === 0) return 0; // 如果没有可行的分割方式,返回0
  else if (res.length === 1) return res[0]; // 如果只有一种分割方式,返回该分割次数
  else return -1; // 如果有多种分割方式,返回-1
}

// 递归函数,用于尝试所有可能的分割方式
function recursive(preSum, n, start, count, res) {
  // 如果已经遍历到字符串的末尾,将当前的分割次数加入res中
  if (start === n) {
    res.push(count);
    return;
  }

  // 遍历所有可能的分割点
  for (let end = start + 1; end <= n; end++) {
    // 计算从start到end-1的子串的ASCII码之和
    const sum = preSum[end] - preSum[start];
    // 如果该和是水仙花数,继续递归
    if (isSxh(sum)) {
      recursive(preSum, n, end, count + 1, res);
    }
  }
}

/* 判断入参是否为水仙花数 */
function isSxh(num) {
  // 水仙花数必须是三位数
  if (num <= 99 || num >= 1000) return false;

  // 分解出百位、十位和个位数字
  const x = parseInt(num / 100) % 10;
  const y = parseInt(num / 10) % 10;
  const z = num % 10;

  // 判断是否为水仙花数
  return num == x * x * x + y * y * y + z * z * z;
}

代码逻辑讲解

  1. 输入处理

    • 使用readline模块从控制台读取输入。
    • 每次输入一行时,调用getResult函数处理输入,并输出结果。
  2. ASCII数组转换

    • 将输入字符串转换为ASCII数组cArr,每个字符通过charCodeAt()方法获取其ASCII码。
  3. 前缀和数组

    • 创建一个前缀和数组preSum,用于快速计算任意区间的ASCII码之和。
    • preSum[i]表示字符串前i个字符的ASCII码之和。
  4. 递归分割

    • recursive函数用于递归地尝试所有可能的分割方式。
    • start表示当前分割的起始位置,end表示当前分割的结束位置。
    • 如果start等于字符串长度n,说明已经遍历完整个字符串,将当前的分割次数count加入结果数组res中。
    • 遍历所有可能的分割点end,计算从startend-1的子串的ASCII码之和,如果该和是水仙花数,则继续递归。
  5. 水仙花数判断

    • isSxh函数用于判断一个数是否为水仙花数。
    • 水仙花数必须是三位数,且等于其各位数字的立方和。
  6. 结果处理

    • 根据res数组的大小返回不同的结果:
      • 如果res为空,返回0,表示没有可行的分割方式。
      • 如果res只有一个元素,返回该元素,表示唯一的分割次数。
      • 如果res有多个元素,返回-1,表示存在多种分割方式。

代码执行流程

  1. 用户输入一个字符串。
  2. 将字符串转换为ASCII数组,并计算前缀和数组。
  3. 调用递归函数recursive,尝试所有可能的分割方式。
  4. 在递归过程中,判断每个子串的ASCII码之和是否为水仙花数。
  5. 根据递归结果,返回相应的分割次数或-1。

代码的局限性

  1. 性能问题

    • 由于使用了递归,且每次递归都会遍历所有可能的分割点,时间复杂度较高,对于较长的字符串可能会导致性能问题。
    • 可以通过动态规划或记忆化搜索优化递归过程。
  2. 水仙花数范围

    • 代码中只考虑了三位数的水仙花数,如果需要处理其他位数的水仙花数,需要修改isSxh函数。
  3. 输入限制

    • 代码假设输入是一个有效的字符串,未处理空字符串或非法输入的情况。

示例运行

输入:
abc
输出:
0
解释:
  • 字符串abc的ASCII码分别为97, 98, 99
  • 没有任何子串的ASCII码之和是三位数的水仙花数,因此返回0

输入:
153
输出:
1
解释:
  • 字符串153的ASCII码分别为49, 53, 51
  • 整个字符串的ASCII码之和为49 + 53 + 51 = 153,恰好是水仙花数。
  • 因此,只有一种分割方式,返回1

输入:
370371
输出:
-1
解释:
  • 字符串370371的ASCII码分别为51, 55, 48, 51, 55, 49
  • 存在多种分割方式使得子串的ASCII码之和是水仙花数,因此返回-1

总结

这段代码的主要功能是将字符串分割成若干个子串,使得每个子串的ASCII码之和是一个水仙花数,并返回分割的次数。代码通过前缀和数组和递归实现了这一功能,但由于递归的使用,可能会导致性能问题。可以通过优化算法(如动态规划)来提升性能。

三、Java算法源码

代码详细注释与讲解

以下是对你提供的Java代码的详细注释和讲解。代码的主要功能是将一个字符串分割成若干个子串,使得每个子串的ASCII码之和是一个“水仙花数”,并返回分割的次数。如果存在多种分割方式,返回-1;如果没有可行的分割方式,返回0。

import java.util.ArrayList;
import java.util.Scanner;

public class Main {
  public static void main(String[] args) {
    // 使用Scanner读取输入,并设置分隔符为换行符
    Scanner sc = new Scanner(System.in).useDelimiter("[\n]");
    // 读取输入字符串并调用getResult方法,输出结果
    System.out.println(getResult(sc.next()));
  }

  // 获取字符串分割结果的函数
  public static int getResult(String s) {
    // 将字符串转化为字符数组
    char[] cArr = s.toCharArray();

    // 获取字符数组的长度
    int n = cArr.length;

    // 创建前缀和数组,用于快速计算任意区间的ASCII码之和
    int[] preSum = new int[n + 1];
    // 计算前缀和
    for (int i = 1; i <= n; i++) preSum[i] = preSum[i - 1] + cArr[i - 1];

    // 用于存储所有可能的分割次数
    ArrayList<Integer> res = new ArrayList<>();
    // 调用递归函数,从字符串的起始位置开始递归
    recursive(preSum, n, 0, 0, res);

    // 根据res的大小返回不同的结果
    if (res.size() == 0) return 0; // 如果没有可行的分割方式,返回0
    else if (res.size() == 1) return res.get(0); // 如果只有一种分割方式,返回该分割次数
    else return -1; // 如果有多种分割方式,返回-1
  }

  // 递归函数,用于尝试所有可能的分割方式
  public static void recursive(int[] preSum, int n, int start, int count, ArrayList<Integer> res) {
    // 如果已经遍历到字符串的末尾,将当前的分割次数加入res中
    if (start == n) {
      res.add(count);
      return;
    }

    // 遍历所有可能的分割点
    for (int end = start + 1; end <= n; end++) {
      // 计算从start到end-1的子串的ASCII码之和
      int sum = preSum[end] - preSum[start];
      // 如果该和是水仙花数,继续递归
      if (isSxh(sum)) {
        recursive(preSum, n, end, count + 1, res);
      }
    }
  }

  // 判断一个数是否为水仙花数
  public static boolean isSxh(int num) {
    // 水仙花数必须是三位数
    if (num <= 99 || num >= 1000) return false;

    // 分解出百位、十位和个位数字
    int x = num / 100 % 10;
    int y = num / 10 % 10;
    int z = num % 10;

    // 判断是否为水仙花数
    return num == x * x * x + y * y * y + z * z * z;
  }
}

代码逻辑讲解

  1. 输入处理

    • 使用Scanner读取输入字符串,并设置分隔符为换行符。
    • 调用getResult方法处理字符串,并输出结果。
  2. 前缀和数组

    • 将字符串转换为字符数组cArr
    • 创建一个前缀和数组preSum,用于快速计算任意区间的ASCII码之和。preSum[i]表示字符串前i个字符的ASCII码之和。
  3. 递归分割

    • recursive函数用于递归地尝试所有可能的分割方式。
    • start表示当前分割的起始位置,end表示当前分割的结束位置。
    • 如果start等于字符串长度n,说明已经遍历完整个字符串,将当前的分割次数count加入结果列表res中。
    • 遍历所有可能的分割点end,计算从startend-1的子串的ASCII码之和,如果该和是水仙花数,则继续递归。
  4. 水仙花数判断

    • isSxh函数用于判断一个数是否为水仙花数。
    • 水仙花数必须是三位数,且等于其各位数字的立方和。
  5. 结果处理

    • 根据res列表的大小返回不同的结果:
      • 如果res为空,返回0,表示没有可行的分割方式。
      • 如果res只有一个元素,返回该元素,表示唯一的分割次数。
      • 如果res有多个元素,返回-1,表示存在多种分割方式。

代码执行流程

  1. 用户输入一个字符串。
  2. 将字符串转换为字符数组,并计算前缀和数组。
  3. 调用递归函数recursive,尝试所有可能的分割方式。
  4. 在递归过程中,判断每个子串的ASCII码之和是否为水仙花数。
  5. 根据递归结果,返回相应的分割次数或-1。

代码的局限性

  • 性能问题:由于使用了递归,且每次递归都会遍历所有可能的分割点,时间复杂度较高,对于较长的字符串可能会导致性能问题。
  • 水仙花数范围:代码中只考虑了三位数的水仙花数,如果需要处理其他位数的水仙花数,需要修改isSxh函数。

总结

这段代码的主要功能是将字符串分割成若干个子串,使得每个子串的ASCII码之和是一个水仙花数,并返回分割的次数。代码通过前缀和数组和递归实现了这一功能,但由于递归的使用,可能会导致性能问题。

四、Python算法源码

代码详细注释与讲解

以下是对你提供的Python代码的详细注释和讲解。代码的主要功能是将一个字符串分割成若干个子串,使得每个子串的ASCII码之和是一个“水仙花数”,并返回分割的次数。如果存在多种分割方式,返回-1;如果没有可行的分割方式,返回0。

# 输入获取
s = input()


# 判断num是否为水仙花数
def isSxh(num):
    # 水仙花数必须是三位数
    if num <= 99 or num >= 1000:
        return False

    # 分解出百位、十位和个位数字
    x, y, z = [int(c) for c in str(num)]

    # 判断是否为水仙花数
    return num == x ** 3 + y ** 3 + z ** 3


# 递归分割
def recursive(preSum, n, start, count, res):
    # 如果已经遍历到字符串的末尾,将当前的分割次数加入res中
    if start == n:
        res.append(count)
        return

    # 遍历所有可能的分割点
    for end in range(start + 1, n + 1):
        # 计算从start到end-1的子串的ASCII码之和
        if isSxh(preSum[end] - preSum[start]):
            # 如果该和是水仙花数,继续递归
            recursive(preSum, n, end, count + 1, res)


# 算法入口
def getResult():
    # 将字符串转化为ASCII数组
    cArr = [ord(c) for c in s]

    # 获取字符数组的长度
    n = len(cArr)

    # 前缀和,实现O(1)时间求解某区间内元素之和
    preSum = [0] * (n + 1)
    for i in range(1, n + 1):
        preSum[i] = preSum[i - 1] + cArr[i - 1]

    # res记录成功分割的情况
    res = []

    # 递归分割
    recursive(preSum, n, 0, 0, res)

    # 根据res的大小返回不同的结果
    if len(res) == 0:
        return 0  # 如果没有可行的分割方式,返回0
    elif len(res) == 1:
        return res[0]  # 如果只有一种分割方式,返回该分割次数
    else:
        return -1  # 如果有多种分割方式,返回-1


# 算法调用
print(getResult())

代码逻辑讲解

  1. 输入处理

    • 使用input()函数获取用户输入的字符串s
  2. 水仙花数判断

    • isSxh函数用于判断一个数是否为水仙花数。
    • 水仙花数必须是三位数,且等于其各位数字的立方和。
    • 将数字转换为字符串,分解出百位、十位和个位数字,并计算其立方和是否等于原数。
  3. 递归分割

    • recursive函数用于递归地尝试所有可能的分割方式。
    • start表示当前分割的起始位置,end表示当前分割的结束位置。
    • 如果start等于字符串长度n,说明已经遍历完整个字符串,将当前的分割次数count加入结果列表res中。
    • 遍历所有可能的分割点end,计算从startend-1的子串的ASCII码之和,如果该和是水仙花数,则继续递归。
  4. 前缀和数组

    • 将字符串转换为ASCII数组cArr
    • 创建一个前缀和数组preSum,用于快速计算任意区间的ASCII码之和。preSum[i]表示字符串前i个字符的ASCII码之和。
  5. 结果处理

    • 根据res列表的大小返回不同的结果:
      • 如果res为空,返回0,表示没有可行的分割方式。
      • 如果res只有一个元素,返回该元素,表示唯一的分割次数。
      • 如果res有多个元素,返回-1,表示存在多种分割方式。

代码执行流程

  1. 用户输入一个字符串。
  2. 将字符串转换为ASCII数组,并计算前缀和数组。
  3. 调用递归函数recursive,尝试所有可能的分割方式。
  4. 在递归过程中,判断每个子串的ASCII码之和是否为水仙花数。
  5. 根据递归结果,返回相应的分割次数或-1。

代码的局限性

  1. 性能问题

    • 由于使用了递归,且每次递归都会遍历所有可能的分割点,时间复杂度较高,对于较长的字符串可能会导致性能问题。
    • 可以通过动态规划或记忆化搜索优化递归过程。
  2. 水仙花数范围

    • 代码中只考虑了三位数的水仙花数,如果需要处理其他位数的水仙花数,需要修改isSxh函数。
  3. 输入限制

    • 代码假设输入是一个有效的字符串,未处理空字符串或非法输入的情况。

示例运行

输入:
abc
输出:
0
解释:
  • 字符串abc的ASCII码分别为97, 98, 99
  • 没有任何子串的ASCII码之和是三位数的水仙花数,因此返回0

输入:
153
输出:
1
解释:
  • 字符串153的ASCII码分别为49, 53, 51
  • 整个字符串的ASCII码之和为49 + 53 + 51 = 153,恰好是水仙花数。
  • 因此,只有一种分割方式,返回1

输入:
370371
输出:
-1
解释:
  • 字符串370371的ASCII码分别为51, 55, 48, 51, 55, 49
  • 存在多种分割方式使得子串的ASCII码之和是水仙花数,因此返回-1

总结

这段代码的主要功能是将字符串分割成若干个子串,使得每个子串的ASCII码之和是一个水仙花数,并返回分割的次数。代码通过前缀和数组和递归实现了这一功能,但由于递归的使用,可能会导致性能问题。可以通过优化算法(如动态规划)来提升性能。

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

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


C++ 实现

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

// 判断num是否为水仙花数
bool isSxh(int num) {
    // 水仙花数必须是三位数
    if (num <= 99 || num >= 1000) return false;

    // 分解出百位、十位和个位数字
    int x = num / 100 % 10;
    int y = num / 10 % 10;
    int z = num % 10;

    // 判断是否为水仙花数
    return num == x * x * x + y * y * y + z * z * z;
}

// 递归分割函数
void recursive(const vector<int>& preSum, int n, int start, int count, vector<int>& res) {
    // 如果已经遍历到字符串的末尾,将当前的分割次数加入res中
    if (start == n) {
        res.push_back(count);
        return;
    }

    // 遍历所有可能的分割点
    for (int end = start + 1; end <= n; end++) {
        // 计算从start到end-1的子串的ASCII码之和
        int sum = preSum[end] - preSum[start];
        // 如果该和是水仙花数,继续递归
        if (isSxh(sum)) {
            recursive(preSum, n, end, count + 1, res);
        }
    }
}

// 获取字符串分割结果的函数
int getResult(const string& str) {
    // 将字符串转化为ASCII数组
    vector<int> cArr;
    for (char c : str) {
        cArr.push_back((int)c);
    }

    int n = cArr.size();

    // 前缀和,实现O(1)时间求解某区间内元素之和
    vector<int> preSum(n + 1, 0);
    for (int i = 1; i <= n; i++) {
        preSum[i] = preSum[i - 1] + cArr[i - 1];
    }

    // res记录成功分割的情况
    vector<int> res;

    // 递归分割
    recursive(preSum, n, 0, 0, res);

    // 根据res的大小返回不同的结果
    if (res.size() == 0) return 0;       // 如果没有可行的分割方式,返回0
    else if (res.size() == 1) return res[0]; // 如果只有一种分割方式,返回该分割次数
    else return -1;                      // 如果有多种分割方式,返回-1
}

int main() {
    string input;
    cin >> input; // 读取输入字符串
    cout << getResult(input) << endl; // 输出结果
    return 0;
}

C语言实现

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

// 判断num是否为水仙花数
bool isSxh(int num) {
    // 水仙花数必须是三位数
    if (num <= 99 || num >= 1000) return false;

    // 分解出百位、十位和个位数字
    int x = num / 100 % 10;
    int y = num / 10 % 10;
    int z = num % 10;

    // 判断是否为水仙花数
    return num == x * x * x + y * y * y + z * z * z;
}

// 递归分割函数
void recursive(int preSum[], int n, int start, int count, int res[], int* resSize) {
    // 如果已经遍历到字符串的末尾,将当前的分割次数加入res中
    if (start == n) {
        res[(*resSize)++] = count;
        return;
    }

    // 遍历所有可能的分割点
    for (int end = start + 1; end <= n; end++) {
        // 计算从start到end-1的子串的ASCII码之和
        int sum = preSum[end] - preSum[start];
        // 如果该和是水仙花数,继续递归
        if (isSxh(sum)) {
            recursive(preSum, n, end, count + 1, res, resSize);
        }
    }
}

// 获取字符串分割结果的函数
int getResult(char* str) {
    int n = strlen(str);

    // 将字符串转化为ASCII数组
    int cArr[n];
    for (int i = 0; i < n; i++) {
        cArr[i] = (int)str[i];
    }

    // 前缀和,实现O(1)时间求解某区间内元素之和
    int preSum[n + 1];
    preSum[0] = 0;
    for (int i = 1; i <= n; i++) {
        preSum[i] = preSum[i - 1] + cArr[i - 1];
    }

    // res记录成功分割的情况
    int res[1000]; // 假设最多1000种分割方式
    int resSize = 0;

    // 递归分割
    recursive(preSum, n, 0, 0, res, &resSize);

    // 根据res的大小返回不同的结果
    if (resSize == 0) return 0;       // 如果没有可行的分割方式,返回0
    else if (resSize == 1) return res[0]; // 如果只有一种分割方式,返回该分割次数
    else return -1;                   // 如果有多种分割方式,返回-1
}

int main() {
    char input[1000]; // 假设输入字符串最大长度为1000
    scanf("%s", input); // 读取输入字符串
    printf("%d\n", getResult(input)); // 输出结果
    return 0;
}

代码逻辑讲解

  1. 输入处理

    • 从控制台读取输入字符串。
    • 将字符串转换为ASCII数组。
  2. 前缀和数组

    • 创建一个前缀和数组preSum,用于快速计算任意区间的ASCII码之和。
    • preSum[i]表示字符串前i个字符的ASCII码之和。
  3. 递归分割

    • recursive函数用于递归地尝试所有可能的分割方式。
    • start表示当前分割的起始位置,end表示当前分割的结束位置。
    • 如果start等于字符串长度n,说明已经遍历完整个字符串,将当前的分割次数count加入结果数组res中。
    • 遍历所有可能的分割点end,计算从startend-1的子串的ASCII码之和,如果该和是水仙花数,则继续递归。
  4. 水仙花数判断

    • isSxh函数用于判断一个数是否为水仙花数。
    • 水仙花数必须是三位数,且等于其各位数字的立方和。
  5. 结果处理

    • 根据res数组的大小返回不同的结果:
      • 如果res为空,返回0,表示没有可行的分割方式。
      • 如果res只有一个元素,返回该元素,表示唯一的分割次数。
      • 如果res有多个元素,返回-1,表示存在多种分割方式。

代码执行流程

  1. 用户输入一个字符串。
  2. 将字符串转换为ASCII数组,并计算前缀和数组。
  3. 调用递归函数recursive,尝试所有可能的分割方式。
  4. 在递归过程中,判断每个子串的ASCII码之和是否为水仙花数。
  5. 根据递归结果,返回相应的分割次数或-1。

代码的局限性

  1. 性能问题

    • 由于使用了递归,且每次递归都会遍历所有可能的分割点,时间复杂度较高,对于较长的字符串可能会导致性能问题。
    • 可以通过动态规划或记忆化搜索优化递归过程。
  2. 水仙花数范围

    • 代码中只考虑了三位数的水仙花数,如果需要处理其他位数的水仙花数,需要修改isSxh函数。
  3. 输入限制

    • 代码假设输入是一个有效的字符串,未处理空字符串或非法输入的情况。

总结

这段代码的主要功能是将字符串分割成若干个子串,使得每个子串的ASCII码之和是一个水仙花数,并返回分割的次数。代码通过前缀和数组和递归实现了这一功能,但由于递归的使用,可能会导致性能问题。可以通过优化算法(如动态规划)来提升性能。

六、尾言

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/956468.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Elasticsearch 和arkime 安装

安装一定要注意版本号&#xff0c;不然使用不了 这里Ubuntu使用ubuntu-20.04.6-desktop-amd64.iso elasticsearch这里使用Elasticsearch 7.17.5 | Elastic arkime这里使用wget https://s3.amazonaws.com/files.molo.ch/builds/ubuntu-20.04/arkime_3.4.2-1_amd64.deb 大家想…

简述mysql 主从复制原理及其工作过程,配置一主两从并验证。

MySQL 主从同步是一种数据库复制技术&#xff0c;它通过将主服务器上的数据更改复制到一个或多个从服务器&#xff0c;实现数据的自动同步。 主从同步的核心原理是将主服务器上的二进制日志复制到从服务器&#xff0c;并在从服务器上执行这些日志中的操作。 MySQL主从同步是基…

MySQL 主从复制原理及其工作过程的配置

一、MySQL主从复制原理 MySQL 主从同步是一种数据库复制技术&#xff0c;它通过将主服务器上的数据更改复制到一个或多个从服务器&#xff0c;实现数据的自动同步。 主从同步的核心原理是将主服务器上的二进制日志复制到从服务器&#xff0c;并在从服务器上执行这些日志中的操作…

多平台下Informatica在医疗数据抽取中的应用

一、引言 1.医疗数据抽取与 Informatica 概述 1.1 医疗数据的特点与来源 1.1.1 数据特点 医疗数据具有显著的多样性特点。从数据类型来看&#xff0c;涵盖了结构化数据&#xff0c;如患者的基本信息、检验检查结果等&#xff0c;这些数据通常以表格形式存储&#xff0c;便于…

智能创造的幕后推手:AIGC浪潮下看AI训练师如何塑造智能未来

文章目录 一、AIGC时代的算法与模型训练概览二、算法与模型训练的关键环节三、AI训练师的角色与职责四、AI训练师的专业技能与素养五、AIGC算法与模型训练的未来展望《AI训练师手册&#xff1a;算法与模型训练从入门到精通》亮点内容简介作者简介谷建阳 目录 《AI智能化办公&am…

有限元分析学习——Anasys Workbanch第一阶段笔记(13)网格单元分类、物理场与自由度概念

目录 0 序言 1 网格单元分类 2 各类单元的应用 3 massage与帮助和查看 4 物理场和自由度 4.1 各种单元自由度 4.2 结构自由度 0 序言 本章主要讲解网格单元的分类及物理场和自由度的相关概念。 1 网格单元分类 按单元的形状分类&#xff1a;实体单元、壳单元和杆梁单元…

RC2在线加密工具

RC2是由著名密码学家Ron Rivest设计的一种传统对称分组加密算法&#xff0c;它可作为DES算法的建议替代算法。RC2是一种分组加密算法&#xff0c;RC2的密钥长度可变&#xff0c;可以从8字节到128字节&#xff0c;安全性选择更加灵活。 开发调试上&#xff0c;有时候需要进行对…

深度学习笔记——循环神经网络RNN

大家好&#xff0c;这里是好评笔记&#xff0c;公主号&#xff1a;Goodnote&#xff0c;专栏文章私信限时Free。本文详细介绍面试过程中可能遇到的循环神经网络RNN知识点。 文章目录 文本特征提取的方法1. 基础方法1.1 词袋模型&#xff08;Bag of Words, BOW&#xff09;工作原…

.NET周刊【1月第1期 2025-01-05】

国内文章 3款.NET开源、功能强大的通讯调试工具&#xff0c;效率提升利器&#xff01; https://www.cnblogs.com/Can-daydayup/p/18631410 本文介绍了三款功能强大的.NET开源通讯调试工具&#xff0c;旨在提高调试效率。这些工具包括LLCOM&#xff0c;提供串口调试和自动化处…

AT8870单通道直流电机驱动芯片

AT8870单通道直流电机驱动芯片 典型应用原理图 描述 AT8870是一款刷式直流电机驱动器&#xff0c;适用于打印机、电器、工业设备以及其他小型机器。两个逻辑输入控制H桥驱动器&#xff0c;该驱动器由四个N-MOS组成&#xff0c;能够以高达3.6A的峰值电流双向控制电机。利用电流…

创建 pdf 合同模板

创建 pdf 合同模板 一、前言二、模板展示三、制作过程 一、前言 前段时间要求创建“pdf”模板&#xff0c;学会了后感觉虽然简单&#xff0c;但开始也折腾了好久&#xff0c;这里做个记录。 二、模板展示 要创建这样的模板 三、制作过程 新建一个“Word”&#xff0c;这里命…

【Go】Go数据类型详解—指针

1. 前言 在我看来&#xff0c;一门编程语言语法的核心就在于数据类型。而各类编程语言的基本数据类型大致相同&#xff1a;int整型、float浮点型、string字符串类型、bool布尔类型&#xff0c;但是在一些进阶数据类型上就有所不同了。本文将会介绍Go语言当中核心的数据类型——…

CSS 圆形头像和破图时显示默认图片

一、需求 1、css实现圆形头像 2、破图是显示默认图片 二、实现 <img :src"photoSrc" class"circle-avatar" :width"size" :height"size" error"handleImageError" //破图时使用的方法 > <style> .circl…

SpringBoot+Vue小区智享物业管理系统(高质量源码,可定制,提供文档,免费部署到本地)

作者简介&#xff1a;✌CSDN新星计划导师、Java领域优质创作者、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和学生毕业项目实战,高校老师/讲师/同行前辈交流。✌ 主要内容&#xff1a;&#x1f31f;Java项目、Python项目、前端项目、PHP、ASP.NET、人工智能…

jenkins-视图管理

一. 简述&#xff1b; jenkins默认只有一个All的view&#xff0c; 在我们线上环境中(测试、预发布、线上、端、语言环境等)&#xff0c;显然是不合理的(放在一个view中不编译管理)。我们可以通过一个dashboard view的插件来进行多个view(按环境&#xff0c;业务等分隔均可)管理…

Transformer详解:Attention机制原理

前言 Hello&#xff0c;大家好&#xff0c;我是GISer Liu&#x1f601;&#xff0c;一名热爱AI技术的GIS开发者&#xff0c;本系列文章是作者参加DataWhale2025年1月份学习赛&#xff0c;旨在讲解Transformer模型的理论和实践。&#x1f632; 本文将详细探讨Attention机制的原理…

PHP变量

目录 变量的定义 预定义变量 $_SERVER $_GET $_POST $_REQUEST $_COOKIE $_SESSION $_FILES 变量作用域 global 关键字 static 变量 可变变量 完结 上一篇文章已经学习了PHP的数据类型&#xff0c;今天将学习新的内容&#xff1a;变量。 变量的定义 PHP 中变量…

四、CSS效果

一、box-shadow box-shadow:在元素的框架上添加阴影效果 /* x 偏移量 | y 偏移量 | 阴影颜色 */ box-shadow: 60px -16px teal; /* x 偏移量 | y 偏移量 | 阴影模糊半径 | 阴影颜色 */ box-shadow: 10px 5px 5px black; /* x 偏移量 | y 偏移量 | 阴影模糊半径 | 阴影扩散半…

STM32 FreeRTOS 事件标志组

目录 事件标志组简介 基本概念 1、事件位&#xff08;事件标志&#xff09; 2、事件组 事件组和事件位数据类型 事件标志组和信号量的区别 事件标志组相关API函数介绍 事件标志组简介 基本概念 当在嵌入式系统中运行多个任务时&#xff0c;这些任务可能需要相互通信&am…

【网络原理】万字详解 HTTP 协议

&#x1f970;&#x1f970;&#x1f970;来都来了&#xff0c;不妨点个关注叭&#xff01; &#x1f449;博客主页&#xff1a;欢迎各位大佬!&#x1f448; 文章目录 1. HTTP 前置知识1.1 HTTP 是什么1.2 HTPP 协议应用场景1.3 HTTP 协议工作过程 2. HTTP 协议格式2.1 fiddler…