【2024年华为OD机试】(B卷,100分)- 非严格递增连续数字序列 (JavaScriptJava PythonC/C++)

news2025/5/31 19:23:24

在这里插入图片描述

一、问题描述

题目描述

给定一个仅包含大小写字母和数字的字符串,要求找出其中最长的非严格递增连续数字序列的长度。非严格递增连续数字序列指的是序列中的数字从左到右依次递增或保持不变,例如 12234 就是一个非严格递增连续数字序列。

输入描述

输入一个字符串,仅包含大小写字母和数字,且字符串的最大长度不超过255个字符。

输出描述

输出字符串中最长的非严格递增连续数字序列的长度。

用例

输入: abc2234019A334bc

输出: 4

说明: 2234 是最长的非严格递增连续数字序列,因此长度为4。

双指针解法

双指针逻辑

  1. 初始化指针:

    • 使用两个指针 leftright,初始时都指向字符串的起始位置。
  2. 遍历字符串:

    • 移动 right 指针,逐个检查字符。
  3. 遇到字母时:

    • 如果 right 指针指向的字符是字母,则说明前面的子串可能是一个符合题意的数字序列。
    • 计算当前子串的长度 right - left,并更新最大长度。
    • leftright 指针同时移动到字母后的下一个位置,继续遍历。
  4. 遇到数字时:

    • 如果 leftright 指针指向同一个位置,说明当前子串长度为1,直接记录。
    • 如果 leftright 指针不在同一个位置,则检查 right 指针指向的数字是否大于或等于 right-1 指针指向的数字:
      • 如果是,则当前子串长度增加,继续移动 right 指针。
      • 如果不是,则记录当前子串长度,并将 leftright 指针同时移动到当前位置的下一个位置,继续遍历。
  5. 结束遍历:

    • 遍历结束后,再次检查最后一个子串的长度,确保没有遗漏。

总结

通过双指针的方法,可以有效地遍历字符串,并在遇到字母或不符合条件的数字时,及时更新最长非严格递增连续数字序列的长度。这种方法的时间复杂度为 O(n),其中 n 是字符串的长度。

二、JavaScript算法源码

以下是 JavaScript 代码的详细注释和讲解,帮助理解每一部分的作用和逻辑:


代码讲解

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

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

// 监听 'line' 事件,当用户输入一行内容时触发
rl.on("line", (line) => {
  // 调用 getMaxLen 函数,计算最长非严格递增连续数字序列的长度,并输出结果
  console.log(getMaxLen(line));
});

// 定义 getMaxLen 函数,用于计算最长非严格递增连续数字序列的长度
function getMaxLen(str) {
  // 初始化双指针 L 和 R,分别表示当前数字序列的起始位置和结束位置
  let L = 0;
  let R = 0;

  // 初始化 maxLen,用于记录当前找到的最长非严格递增连续数字序列的长度
  let maxLen = 0;

  // 遍历字符串
  while (R < str.length) {
    // 判断当前字符是否是数字
    if (/\d/.test(str[R])) {
      // 如果 L 和 R 不在同一个位置,说明当前正在处理一个数字序列
      if (L !== R) {
        // 判断当前字符是否大于等于前一个字符(非严格递增)
        if (str[R] - 0 >= str[R - 1] - 0) {
          // 如果是非严格递增,则更新当前序列的长度(R - L + 1),并更新 maxLen
          maxLen = Math.max(maxLen, R - L + 1);
          // 移动 R 指针,继续检查下一个字符
          R++;
        } else {
          // 如果不是非严格递增,则记录当前序列的长度(R - L),并更新 maxLen
          maxLen = Math.max(maxLen, R - L);
          // 将 L 移动到 R 的位置,开始一个新的数字序列
          L = R;
          // 移动 R 指针,继续检查下一个字符
          R++;
        }
      } else {
        // 如果 L 和 R 在同一个位置,说明当前是一个新的数字序列,长度为 1
        maxLen = Math.max(maxLen, 1);
        // 移动 R 指针,继续检查下一个字符
        R++;
      }
    } else {
      // 如果当前字符不是数字,则记录当前数字序列的长度(R - L),并更新 maxLen
      maxLen = Math.max(maxLen, R - L);
      // 移动 R 指针到下一个字符
      R++;
      // 将 L 移动到 R 的位置,开始一个新的序列
      L = R;
    }
  }

  // 返回最终找到的最长非严格递增连续数字序列的长度
  return maxLen;
}

代码逻辑详解

  1. 输入处理:

    • 使用 readline 模块从控制台读取输入的字符串。
    • 监听 line 事件,当用户输入一行内容时,调用 getMaxLen 函数计算最长非严格递增连续数字序列的长度,并输出结果。
  2. 双指针初始化:

    • LR 分别表示当前数字序列的起始位置和结束位置,初始值均为 0。
    • maxLen 用于记录当前找到的最长非严格递增连续数字序列的长度,初始值为 0。
  3. 遍历字符串:

    • 使用 while 循环遍历字符串,R 指针从 0 开始逐步向右移动。
    • 对于每个字符 str[R],使用正则表达式 /\d/.test(str[R]) 判断其是否是数字:
      • 如果是数字,则进一步判断是否满足非严格递增的条件。
      • 如果不是数字,则记录当前数字序列的长度,并重置 LR 的位置。
  4. 处理数字字符:

    • 如果 LR 不在同一个位置,说明当前正在处理一个数字序列:
      • 判断当前字符是否大于等于前一个字符(非严格递增)。
      • 如果是非严格递增,则更新当前序列的长度(R - L + 1),并更新 maxLen
      • 如果不是非严格递增,则记录当前序列的长度(R - L),并更新 maxLen,同时将 L 移动到 R 的位置,开始一个新的数字序列。
    • 如果 LR 在同一个位置,说明当前是一个新的数字序列,长度为 1,直接更新 maxLen
  5. 处理非数字字符:

    • 如果当前字符不是数字,则记录当前数字序列的长度(R - L),并更新 maxLen
    • LR 移动到下一个字符的位置,开始一个新的序列。
  6. 返回结果:

    • 遍历结束后,返回 maxLen,即最长非严格递增连续数字序列的长度。

示例运行

以输入 abc2234019A334bc 为例:

  1. 遍历到 2 时,开始一个新的数字序列,长度为 1。
  2. 遍历到 2 时,满足非严格递增,序列长度变为 2。
  3. 遍历到 3 时,满足非严格递增,序列长度变为 3。
  4. 遍历到 4 时,满足非严格递增,序列长度变为 4。
  5. 遍历到 0 时,不满足非严格递增,记录当前序列长度 4,并开始新的序列。
  6. 遍历到 1 时,开始新的序列,长度为 1。
  7. 遍历到 9 时,满足非严格递增,序列长度变为 2。
  8. 遍历到 A 时,记录当前序列长度 2,并开始新的序列。
  9. 遍历到 3 时,开始新的序列,长度为 1。
  10. 遍历到 3 时,满足非严格递增,序列长度变为 2。
  11. 遍历到 4 时,满足非严格递增,序列长度变为 3。
  12. 遍历到 b 时,记录当前序列长度 3,并开始新的序列。
  13. 遍历到 c 时,记录当前序列长度 0。

最终,最长非严格递增连续数字序列的长度为 4(2234)。


总结

这段 JavaScript 代码通过双指针的方法,高效地遍历字符串,动态维护当前数字序列的起始和结束位置,并在遇到字母或不满足条件的数字时,及时更新最长序列的长度。代码逻辑清晰,能够正确处理各种边界情况。

三、Java算法源码

以下是代码的详细注释和讲解,帮助理解每一部分的作用和逻辑:


代码讲解

import java.util.Scanner;

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

    // 读取输入的字符串
    String s = sc.nextLine();

    // 调用 getResult 方法,计算最长非严格递增连续数字序列的长度,并输出结果
    System.out.println(getResult(s));
  }

  public static int getResult(String s) {
    // 初始化双指针 l 和 r,分别表示当前数字序列的起始位置和结束位置
    int l = 0;
    int r = 0;

    // 初始化 maxLen,用于记录当前找到的最长非严格递增连续数字序列的长度
    int maxLen = 0;

    // 遍历字符串
    while (r < s.length()) {
      // 获取当前字符
      char c = s.charAt(r);

      // 判断当前字符是否是数字
      if (c >= '0' && c <= '9') {
        // 如果 l 和 r 不在同一个位置,说明当前正在处理一个数字序列
        if (l != r) {
          // 判断当前字符是否大于等于前一个字符(非严格递增)
          if (c >= s.charAt(r - 1)) {
            // 如果是非严格递增,则更新当前序列的长度(r - l + 1),并更新 maxLen
            maxLen = Math.max(maxLen, r - l + 1);
          } else {
            // 如果不是非严格递增,则记录当前序列的长度(r - l),并更新 maxLen
            maxLen = Math.max(maxLen, r - l);
            // 将 l 移动到 r 的位置,开始一个新的数字序列
            l = r;
          }
          // 移动 r 指针,继续检查下一个字符
          r++;
        } else {
          // 如果 l 和 r 在同一个位置,说明当前是一个新的数字序列,长度为 1
          maxLen = Math.max(maxLen, 1);
          // 移动 r 指针,继续检查下一个字符
          r++;
        }
      } else {
        // 如果当前字符不是数字,则记录当前数字序列的长度(r - l),并更新 maxLen
        maxLen = Math.max(maxLen, r - l);
        // 移动 r 指针到下一个字符
        r++;
        // 将 l 移动到 r 的位置,开始一个新的序列
        l = r;
      }
    }

    // 返回最终找到的最长非严格递增连续数字序列的长度
    return maxLen;
  }
}

代码逻辑详解

  1. 输入处理:

    • 使用 Scanner 从控制台读取输入的字符串。
    • 调用 getResult 方法计算最长非严格递增连续数字序列的长度。
  2. 双指针初始化:

    • lr 分别表示当前数字序列的起始位置和结束位置,初始值均为 0。
    • maxLen 用于记录当前找到的最长非严格递增连续数字序列的长度,初始值为 0。
  3. 遍历字符串:

    • 使用 while 循环遍历字符串,r 指针从 0 开始逐步向右移动。
    • 对于每个字符 c,判断其是否是数字:
      • 如果是数字,则进一步判断是否满足非严格递增的条件。
      • 如果不是数字,则记录当前数字序列的长度,并重置 lr 的位置。
  4. 处理数字字符:

    • 如果 lr 不在同一个位置,说明当前正在处理一个数字序列:
      • 判断当前字符是否大于等于前一个字符(非严格递增)。
      • 如果是非严格递增,则更新当前序列的长度(r - l + 1),并更新 maxLen
      • 如果不是非严格递增,则记录当前序列的长度(r - l),并更新 maxLen,同时将 l 移动到 r 的位置,开始一个新的数字序列。
    • 如果 lr 在同一个位置,说明当前是一个新的数字序列,长度为 1,直接更新 maxLen
  5. 处理非数字字符:

    • 如果当前字符不是数字,则记录当前数字序列的长度(r - l),并更新 maxLen
    • lr 移动到下一个字符的位置,开始一个新的序列。
  6. 返回结果:

    • 遍历结束后,返回 maxLen,即最长非严格递增连续数字序列的长度。

示例运行

以输入 abc2234019A334bc 为例:

  1. 遍历到 2 时,开始一个新的数字序列,长度为 1。
  2. 遍历到 2 时,满足非严格递增,序列长度变为 2。
  3. 遍历到 3 时,满足非严格递增,序列长度变为 3。
  4. 遍历到 4 时,满足非严格递增,序列长度变为 4。
  5. 遍历到 0 时,不满足非严格递增,记录当前序列长度 4,并开始新的序列。
  6. 遍历到 1 时,开始新的序列,长度为 1。
  7. 遍历到 9 时,满足非严格递增,序列长度变为 2。
  8. 遍历到 A 时,记录当前序列长度 2,并开始新的序列。
  9. 遍历到 3 时,开始新的序列,长度为 1。
  10. 遍历到 3 时,满足非严格递增,序列长度变为 2。
  11. 遍历到 4 时,满足非严格递增,序列长度变为 3。
  12. 遍历到 b 时,记录当前序列长度 3,并开始新的序列。
  13. 遍历到 c 时,记录当前序列长度 0。

最终,最长非严格递增连续数字序列的长度为 4(2234)。


总结

这段代码通过双指针的方法,高效地遍历字符串,动态维护当前数字序列的起始和结束位置,并在遇到字母或不满足条件的数字时,及时更新最长序列的长度。代码逻辑清晰,能够正确处理各种边界情况。

四、Python算法源码

以下是 Python 代码的详细注释和讲解,帮助理解每一部分的作用和逻辑:


代码讲解

# 输入获取
s = input()

# 算法入口
def getResult():
    # 初始化双指针 l 和 r,分别表示当前数字序列的起始位置和结束位置
    l = 0
    r = 0

    # 初始化 maxLen,用于记录当前找到的最长非严格递增连续数字序列的长度
    maxLen = 0

    # 遍历字符串
    while r < len(s):
        # 判断当前字符是否是数字
        if '0' <= s[r] <= '9':
            # 如果 l 和 r 不在同一个位置,说明当前正在处理一个数字序列
            if l != r:
                # 判断当前字符是否大于等于前一个字符(非严格递增)
                if s[r] >= s[r-1]:
                    # 如果是非严格递增,则更新当前序列的长度(r - l + 1),并更新 maxLen
                    maxLen = max(maxLen, r - l + 1)
                    # 移动 r 指针,继续检查下一个字符
                    r += 1
                else:
                    # 如果不是非严格递增,则记录当前序列的长度(r - l),并更新 maxLen
                    maxLen = max(maxLen, r - l)
                    # 将 l 移动到 r 的位置,开始一个新的数字序列
                    l = r
                    # 移动 r 指针,继续检查下一个字符
                    r += 1
            else:
                # 如果 l 和 r 在同一个位置,说明当前是一个新的数字序列,长度为 1
                maxLen = max(maxLen, 1)
                # 移动 r 指针,继续检查下一个字符
                r += 1
        else:
            # 如果当前字符不是数字,则记录当前数字序列的长度(r - l),并更新 maxLen
            maxLen = max(maxLen, r - l)
            # 移动 r 指针到下一个字符
            r += 1
            # 将 l 移动到 r 的位置,开始一个新的序列
            l = r

    # 返回最终找到的最长非严格递增连续数字序列的长度
    return maxLen

# 调用算法
print(getResult())

代码逻辑详解

  1. 输入处理:

    • 使用 input() 函数从控制台读取输入的字符串。
  2. 双指针初始化:

    • lr 分别表示当前数字序列的起始位置和结束位置,初始值均为 0。
    • maxLen 用于记录当前找到的最长非严格递增连续数字序列的长度,初始值为 0。
  3. 遍历字符串:

    • 使用 while 循环遍历字符串,r 指针从 0 开始逐步向右移动。
    • 对于每个字符 s[r],判断其是否是数字:
      • 如果是数字,则进一步判断是否满足非严格递增的条件。
      • 如果不是数字,则记录当前数字序列的长度,并重置 lr 的位置。
  4. 处理数字字符:

    • 如果 lr 不在同一个位置,说明当前正在处理一个数字序列:
      • 判断当前字符是否大于等于前一个字符(非严格递增)。
      • 如果是非严格递增,则更新当前序列的长度(r - l + 1),并更新 maxLen
      • 如果不是非严格递增,则记录当前序列的长度(r - l),并更新 maxLen,同时将 l 移动到 r 的位置,开始一个新的数字序列。
    • 如果 lr 在同一个位置,说明当前是一个新的数字序列,长度为 1,直接更新 maxLen
  5. 处理非数字字符:

    • 如果当前字符不是数字,则记录当前数字序列的长度(r - l),并更新 maxLen
    • lr 移动到下一个字符的位置,开始一个新的序列。
  6. 返回结果:

    • 遍历结束后,返回 maxLen,即最长非严格递增连续数字序列的长度。

示例运行

以输入 abc2234019A334bc 为例:

  1. 遍历到 2 时,开始一个新的数字序列,长度为 1。
  2. 遍历到 2 时,满足非严格递增,序列长度变为 2。
  3. 遍历到 3 时,满足非严格递增,序列长度变为 3。
  4. 遍历到 4 时,满足非严格递增,序列长度变为 4。
  5. 遍历到 0 时,不满足非严格递增,记录当前序列长度 4,并开始新的序列。
  6. 遍历到 1 时,开始新的序列,长度为 1。
  7. 遍历到 9 时,满足非严格递增,序列长度变为 2。
  8. 遍历到 A 时,记录当前序列长度 2,并开始新的序列。
  9. 遍历到 3 时,开始新的序列,长度为 1。
  10. 遍历到 3 时,满足非严格递增,序列长度变为 2。
  11. 遍历到 4 时,满足非严格递增,序列长度变为 3。
  12. 遍历到 b 时,记录当前序列长度 3,并开始新的序列。
  13. 遍历到 c 时,记录当前序列长度 0。

最终,最长非严格递增连续数字序列的长度为 4(2234)。


总结

这段 Python 代码通过双指针的方法,高效地遍历字符串,动态维护当前数字序列的起始和结束位置,并在遇到字母或不满足条件的数字时,及时更新最长序列的长度。代码逻辑清晰,能够正确处理各种边界情况。

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

以下是 C++C语言 代码的中文详细注释和讲解,帮助理解每一部分的作用和逻辑:


C++ 代码

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

// 定义宏 MAX,用于比较两个数的大小并返回较大的值
#define MAX(a, b) (a > b ? a : b)

int main() {
    // 定义字符串 s,用于存储输入的字符串
    string s;
    // 使用 cin 从控制台读取输入的字符串
    cin >> s;

    // 初始化双指针 l 和 r,分别表示当前数字序列的起始位置和结束位置
    int l = 0;
    int r = 0;

    // 初始化 maxLen,用于记录当前找到的最长非严格递增连续数字序列的长度
    int maxLen = 0;

    // 遍历字符串
    while (r < s.length()) {
        // 获取当前字符
        char c = s[r];

        // 判断当前字符是否是数字
        if (c >= '0' && c <= '9') {
            // 如果 l 和 r 不在同一个位置,说明当前正在处理一个数字序列
            if (l != r) {
                // 判断当前字符是否大于等于前一个字符(非严格递增)
                if (c >= s[r - 1]) {
                    // 如果是非严格递增,则更新当前序列的长度(r - l + 1),并更新 maxLen
                    maxLen = MAX(maxLen, r - l + 1);
                } else {
                    // 如果不是非严格递增,则记录当前序列的长度(r - l),并更新 maxLen
                    maxLen = MAX(maxLen, r - l);
                    // 将 l 移动到 r 的位置,开始一个新的数字序列
                    l = r;
                }
                // 移动 r 指针,继续检查下一个字符
                r++;
            } else {
                // 如果 l 和 r 在同一个位置,说明当前是一个新的数字序列,长度为 1
                maxLen = MAX(maxLen, 1);
                // 移动 r 指针,继续检查下一个字符
                r++;
            }
        } else {
            // 如果当前字符不是数字,则记录当前数字序列的长度(r - l),并更新 maxLen
            maxLen = MAX(maxLen, r - l);
            // 移动 r 指针到下一个字符
            r++;
            // 将 l 移动到 r 的位置,开始一个新的序列
            l = r;
        }
    }

    // 输出最终找到的最长非严格递增连续数字序列的长度
    cout << maxLen << endl;

    return 0;
}

C 语言代码

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

// 定义宏 MAX,用于比较两个数的大小并返回较大的值
#define MAX(a, b) (a > b ? a : b)

int main() {
    // 定义字符数组 s,用于存储输入的字符串,最大长度为 255
    char s[255];
    // 使用 scanf 从控制台读取输入的字符串
    scanf("%s", s);

    // 初始化双指针 l 和 r,分别表示当前数字序列的起始位置和结束位置
    int l = 0;
    int r = 0;

    // 初始化 maxLen,用于记录当前找到的最长非严格递增连续数字序列的长度
    int maxLen = 0;

    // 遍历字符串
    while (r < strlen(s)) {
        // 获取当前字符
        char c = s[r];

        // 判断当前字符是否是数字
        if (c >= '0' && c <= '9') {
            // 如果 l 和 r 不在同一个位置,说明当前正在处理一个数字序列
            if (l != r) {
                // 判断当前字符是否大于等于前一个字符(非严格递增)
                if (c >= s[r - 1]) {
                    // 如果是非严格递增,则更新当前序列的长度(r - l + 1),并更新 maxLen
                    maxLen = MAX(maxLen, r - l + 1);
                } else {
                    // 如果不是非严格递增,则记录当前序列的长度(r - l),并更新 maxLen
                    maxLen = MAX(maxLen, r - l);
                    // 将 l 移动到 r 的位置,开始一个新的数字序列
                    l = r;
                }
                // 移动 r 指针,继续检查下一个字符
                r++;
            } else {
                // 如果 l 和 r 在同一个位置,说明当前是一个新的数字序列,长度为 1
                maxLen = MAX(maxLen, 1);
                // 移动 r 指针,继续检查下一个字符
                r++;
            }
        } else {
            // 如果当前字符不是数字,则记录当前数字序列的长度(r - l),并更新 maxLen
            maxLen = MAX(maxLen, r - l);
            // 移动 r 指针到下一个字符
            r++;
            // 将 l 移动到 r 的位置,开始一个新的序列
            l = r;
        }
    }

    // 输出最终找到的最长非严格递增连续数字序列的长度
    printf("%d\n", maxLen);

    return 0;
}

代码逻辑详解

  1. 输入处理:

    • C++: 使用 cin 从控制台读取输入的字符串。
    • C: 使用 scanf 从控制台读取输入的字符串。
  2. 双指针初始化:

    • lr 分别表示当前数字序列的起始位置和结束位置,初始值均为 0。
    • maxLen 用于记录当前找到的最长非严格递增连续数字序列的长度,初始值为 0。
  3. 遍历字符串:

    • 使用 while 循环遍历字符串,r 指针从 0 开始逐步向右移动。
    • 对于每个字符 s[r],判断其是否是数字:
      • 如果是数字,则进一步判断是否满足非严格递增的条件。
      • 如果不是数字,则记录当前数字序列的长度,并重置 lr 的位置。
  4. 处理数字字符:

    • 如果 lr 不在同一个位置,说明当前正在处理一个数字序列:
      • 判断当前字符是否大于等于前一个字符(非严格递增)。
      • 如果是非严格递增,则更新当前序列的长度(r - l + 1),并更新 maxLen
      • 如果不是非严格递增,则记录当前序列的长度(r - l),并更新 maxLen,同时将 l 移动到 r 的位置,开始一个新的数字序列。
    • 如果 lr 在同一个位置,说明当前是一个新的数字序列,长度为 1,直接更新 maxLen
  5. 处理非数字字符:

    • 如果当前字符不是数字,则记录当前数字序列的长度(r - l),并更新 maxLen
    • lr 移动到下一个字符的位置,开始一个新的序列。
  6. 输出结果:

    • C++: 使用 cout 输出结果。
    • C: 使用 printf 输出结果。

示例运行

以输入 abc2234019A334bc 为例:

  1. 遍历到 2 时,开始一个新的数字序列,长度为 1。
  2. 遍历到 2 时,满足非严格递增,序列长度变为 2。
  3. 遍历到 3 时,满足非严格递增,序列长度变为 3。
  4. 遍历到 4 时,满足非严格递增,序列长度变为 4。
  5. 遍历到 0 时,不满足非严格递增,记录当前序列长度 4,并开始新的序列。
  6. 遍历到 1 时,开始新的序列,长度为 1。
  7. 遍历到 9 时,满足非严格递增,序列长度变为 2。
  8. 遍历到 A 时,记录当前序列长度 2,并开始新的序列。
  9. 遍历到 3 时,开始新的序列,长度为 1。
  10. 遍历到 3 时,满足非严格递增,序列长度变为 2。
  11. 遍历到 4 时,满足非严格递增,序列长度变为 3。
  12. 遍历到 b 时,记录当前序列长度 3,并开始新的序列。
  13. 遍历到 c 时,记录当前序列长度 0。

最终,最长非严格递增连续数字序列的长度为 4(2234)。


在这里插入图片描述

总结

  • C++C 代码逻辑一致,均通过双指针的方法高效地遍历字符串。
  • 动态维护当前数字序列的起始和结束位置,并在遇到字母或不满足条件的数字时,及时更新最长序列的长度。
  • 代码逻辑清晰,能够正确处理各种边界情况。

单指针解法

解法逻辑

  1. 初始化变量:

    • 使用一个变量 len 来记录当前非严格递增连续数字序列的长度。
    • 使用一个变量 maxNum 来记录当前序列中最大的数字字符。
    • 使用一个变量 maxLen 来记录全局最长非严格递增连续数字序列的长度。
  2. 遍历字符串:

    • 从左到右逐个扫描字符串中的字符。
  3. 遇到字母时:

    • 如果当前字符是字母,则重置 lenmaxNum
      • len = 0,表示当前序列长度为0。
      • maxNum = 0,表示当前序列中最大的数字字符为0。
  4. 遇到数字时:

    • 如果 len 为0,说明当前数字是序列的开头:
      • 设置 len = 1,表示当前序列长度为1。
      • 设置 maxNum 为当前数字字符的值。
    • 如果 len 不为0,说明当前数字前面还有数字:
      • 判断当前数字是否大于等于 maxNum
        • 如果是,则当前序列可以继续延长,len++,并更新 maxNum 为当前数字字符的值。
        • 如果不是,则当前序列中断,重置 len = 1,并更新 maxNum 为当前数字字符的值。
    • 每次更新 len 后,检查是否需要更新 maxLen
  5. 结束遍历:

    • 遍历结束后,maxLen 即为最长非严格递增连续数字序列的长度。

示例运行

以输入 abc2234019A334bc 为例:

  1. 遍历到 2 时:
    • len = 1maxNum = 2maxLen = 1
  2. 遍历到 2 时:
    • 当前数字 2 大于等于 maxNumlen++maxNum = 2maxLen = 2
  3. 遍历到 3 时:
    • 当前数字 3 大于等于 maxNumlen++maxNum = 3maxLen = 3
  4. 遍历到 4 时:
    • 当前数字 4 大于等于 maxNumlen++maxNum = 4maxLen = 4
  5. 遍历到 0 时:
    • 当前数字 0 小于 maxNum,重置 len = 1maxNum = 0maxLen 仍为4。
  6. 遍历到 1 时:
    • 当前数字 1 大于等于 maxNumlen++maxNum = 1maxLen 仍为4。
  7. 遍历到 9 时:
    • 当前数字 9 大于等于 maxNumlen++maxNum = 9maxLen 仍为4。
  8. 遍历到 A 时:
    • 当前字符是字母,重置 len = 0maxNum = 0maxLen 仍为4。
  9. 遍历到 3 时:
    • len = 1maxNum = 3maxLen 仍为4。
  10. 遍历到 3 时:
    • 当前数字 3 大于等于 maxNumlen++maxNum = 3maxLen 仍为4。
  11. 遍历到 4 时:
    • 当前数字 4 大于等于 maxNumlen++maxNum = 4maxLen 仍为4。
  12. 遍历到 b 时:
    • 当前字符是字母,重置 len = 0maxNum = 0maxLen 仍为4。
  13. 遍历到 c 时:
    • 当前字符是字母,重置 len = 0maxNum = 0maxLen 仍为4。

最终,最长非严格递增连续数字序列的长度为 4(2234)。


总结

  • 单指针解法通过一个变量 len 记录当前序列的长度,另一个变量 maxNum 记录当前序列中最大的数字字符。
  • 每次遇到数字时,根据当前数字与 maxNum 的关系更新 lenmaxNum,并实时更新全局最大值 maxLen
  • 该解法避免了双指针的繁琐逻辑,代码更加简洁高效。

以下是 JavaJavaScriptPythonC 四种语言的代码详细注释和讲解,帮助理解每一部分的作用和逻辑:


Java 代码

import java.util.Scanner;

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

    // 读取输入的字符串
    String s = sc.nextLine();

    // 调用 getResult 方法,计算最长非严格递增连续数字序列的长度,并输出结果
    System.out.println(getResult(s));
  }

  public static int getResult(String s) {
    // 初始化变量 maxNum,用于记录当前数字序列中的最大数字
    int maxNum = 0;

    // 初始化变量 len,用于记录当前非严格递增连续数字序列的长度
    int len = 0;

    // 初始化变量 maxLen,用于记录全局最长非严格递增连续数字序列的长度
    int maxLen = 0;

    // 遍历字符串
    for (int i = 0; i < s.length(); i++) {
      // 获取当前字符
      char c = s.charAt(i);

      // 判断当前字符是否是数字
      if (c >= '0' && c <= '9') {
        // 将字符转换为对应的数字值
        int curNum = c - '0';

        // 如果 len 为 0,说明当前数字是序列的开头
        if (len == 0) {
          // 设置当前序列长度为 1
          len = 1;
          // 更新 maxNum 为当前数字
          maxNum = curNum;
        } else {
          // 如果 len 不为 0,说明当前数字前面还有数字
          // 判断当前数字是否大于等于 maxNum(非严格递增)
          if (curNum >= maxNum) {
            // 如果是非严格递增,则当前序列长度加 1
            len++;
          } else {
            // 如果不是非严格递增,则重置当前序列长度为 1
            len = 1;
          }
          // 更新 maxNum 为当前数字
          maxNum = curNum;
        }
      } else {
        // 如果当前字符不是数字,则重置 len 和 maxNum
        len = 0;
        maxNum = 0;
      }

      // 更新全局最长非严格递增连续数字序列的长度
      maxLen = Math.max(maxLen, len);
    }

    // 返回最终找到的最长非严格递增连续数字序列的长度
    return maxLen;
  }
}

JavaScript 代码

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

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

// 监听 'line' 事件,当用户输入一行内容时触发
rl.on("line", (line) => {
  // 调用 getMaxLen 函数,计算最长非严格递增连续数字序列的长度,并输出结果
  console.log(getMaxLen(line));
});

function getMaxLen(str) {
  // 初始化变量 maxLen,用于记录全局最长非严格递增连续数字序列的长度
  let maxLen = 0;

  // 初始化变量 len,用于记录当前非严格递增连续数字序列的长度
  let len = 0;

  // 初始化变量 maxNum,用于记录当前数字序列中的最大数字
  let maxNum = 0;

  // 遍历字符串
  for (let i = 0; i < str.length; i++) {
    // 判断当前字符是否是数字
    if (/\d/.test(str[i])) {
      // 将字符转换为对应的数字值
      let curNum = str[i] - 0;

      // 如果 len 为 0,说明当前数字是序列的开头
      if (len === 0) {
        // 设置当前序列长度为 1
        len = 1;
        // 更新 maxNum 为当前数字
        maxNum = curNum;
      } else {
        // 如果 len 不为 0,说明当前数字前面还有数字
        // 判断当前数字是否大于等于 maxNum(非严格递增)
        if (curNum >= maxNum) {
          // 如果是非严格递增,则当前序列长度加 1
          len++;
        } else {
          // 如果不是非严格递增,则重置当前序列长度为 1
          len = 1;
        }
        // 更新 maxNum 为当前数字
        maxNum = curNum;
      }
    } else {
      // 如果当前字符不是数字,则重置 len 和 maxNum
      len = 0;
      maxNum = 0;
    }

    // 更新全局最长非严格递增连续数字序列的长度
    maxLen = Math.max(maxLen, len);
  }

  // 返回最终找到的最长非严格递增连续数字序列的长度
  return maxLen;
}

Python 代码

# 输入获取
s = input()

# 算法入口
def getResult():
    # 初始化变量 maxLen,用于记录全局最长非严格递增连续数字序列的长度
    maxLen = 0

    # 初始化变量 length,用于记录当前非严格递增连续数字序列的长度
    length = 0

    # 初始化变量 maxNum,用于记录当前数字序列中的最大数字
    maxNum = 0

    # 遍历字符串
    for c in s:
        # 判断当前字符是否是数字
        if '0' <= c <= '9':
            # 将字符转换为对应的数字值
            curNum = int(c)

            # 如果 length 为 0,说明当前数字是序列的开头
            if length == 0:
                # 设置当前序列长度为 1
                length = 1
                # 更新 maxNum 为当前数字
                maxNum = curNum
            else:
                # 如果 length 不为 0,说明当前数字前面还有数字
                # 判断当前数字是否大于等于 maxNum(非严格递增)
                if curNum >= maxNum:
                    # 如果是非严格递增,则当前序列长度加 1
                    length += 1
                else:
                    # 如果不是非严格递增,则重置当前序列长度为 1
                    length = 1
                # 更新 maxNum 为当前数字
                maxNum = curNum
        else:
            # 如果当前字符不是数字,则重置 length 和 maxNum
            length = 0
            maxNum = 0

        # 更新全局最长非严格递增连续数字序列的长度
        maxLen = max(maxLen, length)

    # 返回最终找到的最长非严格递增连续数字序列的长度
    return maxLen

# 调用算法
print(getResult())

C 代码

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

// 定义宏 MAX,用于比较两个数的大小并返回较大的值
#define MAX(a, b) a > b ? a : b

int main() {
    // 定义字符数组 s,用于存储输入的字符串,最大长度为 255
    char s[255];
    // 使用 scanf 从控制台读取输入的字符串
    scanf("%s", s);

    // 初始化变量 maxNum,用于记录当前数字序列中的最大数字
    int maxNum = 0;

    // 初始化变量 len,用于记录当前非严格递增连续数字序列的长度
    int len = 0;

    // 初始化变量 maxLen,用于记录全局最长非严格递增连续数字序列的长度
    int maxLen = 0;

    // 遍历字符串
    for (int i = 0; i < strlen(s); i++) {
        // 判断当前字符是否是数字
        if (s[i] >= '0' && s[i] <= '9') {
            // 将字符转换为对应的数字值
            int curNum = s[i] - '0';

            // 如果 len 为 0,说明当前数字是序列的开头
            if (len == 0) {
                // 设置当前序列长度为 1
                len = 1;
                // 更新 maxNum 为当前数字
                maxNum = curNum;
            } else {
                // 如果 len 不为 0,说明当前数字前面还有数字
                // 判断当前数字是否大于等于 maxNum(非严格递增)
                if (curNum >= maxNum) {
                    // 如果是非严格递增,则当前序列长度加 1
                    len++;
                } else {
                    // 如果不是非严格递增,则重置当前序列长度为 1
                    len = 1;
                }
                // 更新 maxNum 为当前数字
                maxNum = curNum;
            }
        } else {
            // 如果当前字符不是数字,则重置 len 和 maxNum
            len = 0;
            maxNum = 0;
        }

        // 更新全局最长非严格递增连续数字序列的长度
        maxLen = MAX(maxLen, len);
    }

    // 输出最终找到的最长非严格递增连续数字序列的长度
    printf("%d", maxLen);

    return 0;
}

总结

  • JavaJavaScriptPythonC 四种语言的代码逻辑完全一致。
  • 通过单指针的方法,动态维护当前数字序列的长度和最大数字字符。
  • 每次遇到数字时,根据当前数字与 maxNum 的关系更新 lenmaxNum,并实时更新全局最大值 maxLen
  • 代码逻辑清晰,能够正确处理各种边界情况。

六、尾言

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

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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C# OpenCV机器视觉:红外体温检测

在一个骄阳似火的夏日&#xff0c;全球却被一场突如其来的疫情阴霾笼罩。阿强所在的小镇&#xff0c;平日里熙熙攘攘的街道变得冷冷清清&#xff0c;人们戴着口罩&#xff0c;行色匆匆&#xff0c;眼神中满是对病毒的恐惧。阿强作为镇上小有名气的科技达人&#xff0c;看着这一…

Android Audio音频系统

一、Audio音频架构简介 二、Android Audio系统框架 三、Audio架构以及各层的代码分布图 四、音频框架在Android系统中的进一步细化 五、创建声卡和注册声卡 六、Android Audio系统的结构 七、Audio音频原理介绍 八、Audio音频策略制定与策略执行的调用流程 九、Android…

配电自动化系统“三区四层”数字化架构

目录 一、“三区四层”数字化架构的特点和优势 二、“三区四层”数字化架构面临的挑战 三、针对“三区四层” 数字化架构在实际应用中面临挑战的措施 配电自动化系统 “三区四层” 数字化架构是一种用于规范和指导配电自动化系统建设与运行的体系结构&#xff0c;对保障电力…

编程界“华山论剑”:PHP与Go,谁主沉浮?

在编程的广阔天地里&#xff0c;选择一门合适的编程语言就如同为一场冒险挑选趁手的武器&#xff0c;至关重要却又常常令人纠结。当我们面对 PHP 与 Go 这两种备受瞩目的编程语言时&#xff0c;这种纠结愈发明显&#xff1a;PHP&#xff0c;作为 Web 开发领域的老牌劲旅&#x…

element tbas增加下拉框

使用Tabs 标签页的label插槽&#xff0c;嵌入Dropdown 下拉菜单&#xff0c;实现Tabs 标签页增加下拉切换功能 Tabs 标签页 tab-click"事件"&#xff08;这个事件当中到拥有下拉框的tab里时&#xff0c;可以存一下Dropdown 第一个菜单的id&#xff0c;实现点击到拥有…

AIGC视频生成模型:ByteDance的PixelDance模型

大家好&#xff0c;这里是好评笔记&#xff0c;公主号&#xff1a;Goodnote&#xff0c;专栏文章私信限时Free。本文详细介绍ByteDance的视频生成模型PixelDance&#xff0c;论文于2023年11月发布&#xff0c;模型上线于2024年9月&#xff0c;同时期上线的模型还有Seaweed&…

mysql 学习3 SQL语句--整体概述。SQL通用语法;DDL创建数据库,查看数据库,删除数据库,使用数据库;

SQL通用语法 SQL语句分类 DDL data definition language : 用来创建数据库&#xff0c;创建表&#xff0c;创建表中的字段&#xff0c;创建索引。因此成为 数据定义语言 DML data manipulation language 有了数据库和表以及字段后&#xff0c;那么我们就需要给这个表中 添加数…

Pyside6(PyQT5)中的QTableView与QSqlQueryModel、QSqlTableModel的联合使用

QTableView 是QT的一个强大的表视图部件&#xff0c;可以与模型结合使用以显示和编辑数据。QSqlQueryModel、QSqlTableModel 都是用于与 SQL 数据库交互的模型,将二者与QTableView结合使用可以轻松地展示和编辑数据库的数据。 QSqlQueryModel的简单应用 import sys from PySid…

C语言文件操作:标准库与系统调用实践

目录 1、C语言标准库文件操作 1.1.题目要求&#xff1a; 1.2.函数讲解&#xff1a; fopen 函数原型 参数 常用的打开模式 返回值 fwrite函数 函数原型 参数 返回值 注意事项 fseek函数 函数原型 参数 返回值 fread函数 函数原型 参数 返回值 fclose 函数…

【2024年华为OD机试】 (C卷,100分)- 多段线数据压缩(JavaScriptJava PythonC/C++)

一、问题描述 问题描述 给定一个多线段的坐标列表&#xff0c;每个坐标由行号和列号表示。多线段的走向只能是水平、竖直或斜向45度。输入数据包含冗余的坐标点&#xff0c;要求输出最简化的坐标列表&#xff0c;仅保留起点、拐点和终点。 输入描述 输入数据为多线段的坐标…

状态模式——C++实现

目录 1. 状态模式简介 2. 代码示例 3. 单例状态对象 4. 状态模式与策略模式的辨析 1. 状态模式简介 状态模式是一种行为型模式。 状态模式的定义&#xff1a;状态模式允许对象在内部状态改变时改变它的行为&#xff0c;对象看起来好像修改了它的类。 通俗的说就是一个对象…

数据库SQLite和SCADA DIAView应用教程

课程简介 此系列课程大纲主要包含七个课时。主要使用到的开发工具有&#xff1a;SQLite studio 和 SCADA DIAView。详细的可成内容大概如下&#xff1a; 1、SQLite 可视化管理工具SQLite Studio &#xff1a;打开数据库和查询数据&#xff1b;查看视频 2、创建6个变量&#x…

java开发,IDEA转战VSCODE配置(mac)

一、基本java开发环境配置 前提&#xff1a;已经安装了jdk、maven、vscode&#xff0c;且配置了环境变量 1、安装java相关的插件 2、安装spring相关的插件 3、vscode配置maven环境 打开 VsCode -> 首选项 -> 设置&#xff0c;也可以在setting.json文件中直接编辑&…

python爬虫的学习流程(1-前提准备)

这里主要记录一下我的python爬虫初级的学习的流程 1.python爬虫入门实战课 什么是爬虫&#xff1f;众说纷纭&#xff0c;我们引用维基百科上对网络爬虫的介绍&#xff1a; 网络爬虫&#xff08;英语&#xff1a;Web crawler&#xff09;&#xff0c;也叫网络蜘蛛&#xff08;…

数据结构初阶之双向链表的介绍与双向链表的实现

一、概念与结构 带头双向循环链表 next &#xff1a;指向下一个结点&#xff08;后继结点&#xff09; prev &#xff1a;指向前一个结点&#xff08;前驱结点&#xff09; 二、实现双向链表 项目创建的时候&#xff0c;要创建一个头文件&#xff08;.h&#xff09;List.h …

CICD集合(六):Jenkins配置Editable Email Notification

CICD集合(六):Jenkins配置Editable Email Notification 1、系统配置 1.1、Jenkins Location 1.2、邮件通知 1、SMTP服务器:imap.exmail.qq.com (因qq企业邮箱) 2、邮箱后缀:@xxx.com 3、勾选:使用SMTP认证 用户名:

Golang 中除了加锁还有哪些安全读写共享变量的方式?

Golang 中除了加锁还有哪些安全读写共享变量的方式&#xff1f; 在 Golang 中&#xff0c;除了使用 Mutex 锁来保护共享变量外&#xff0c;还可以通过 Channel 和 原子性操作 来实现安全读写共享变量。 1. 使用 Channel 原理 Channel 是 Golang 中用于 Goroutine 之间通信的…

应用层协议 HTTP 讲解实战:从0实现HTTP 服务器

&#x1f308; 个人主页&#xff1a;Zfox_ &#x1f525; 系列专栏&#xff1a;Linux 目录 一&#xff1a;&#x1f525; HTTP 协议 &#x1f98b; 认识 URL&#x1f98b; urlencode 和 urldecode 二&#xff1a;&#x1f525; HTTP 协议请求与响应格式 &#x1f98b; HTTP 请求…

F/V/F/I频率脉冲信号转换器

F/V/F/I频率脉冲信号转换器 概述&#xff1a;捷晟达科技的JSD TFA-1001系列是一进一出频率脉冲信号转换器(F/V转换器),该频率转换器是将频率脉冲信号(方波、正弦波、锯齿波)转换成国际标准的模拟量电压(电流)信号,并远距离无失真传送到控制室(如:PLC,DCS,AD,PC采集系统)产品的输…

Windows的docker中安装gitlab

一.Windows的docker中安装gitlab 1.通过阿里云拉取镜像 docker pull registry.cn-hangzhou.aliyuncs.com/lab99/gitlab-ce-zh 2.在本地创建备份数据的目录 mkdir -p D:home/software/gitlab/etc mkdir -p D:home/software/gitlab/logs mkdir -p D:home/software/gitlab/dat…