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

在这里插入图片描述

一、问题描述

题目描述

给定一个仅包含大小写字母和数字的字符串,要求找出其中最长的非严格递增连续数字序列的长度。非严格递增连续数字序列指的是序列中的数字从左到右依次递增或保持不变,例如 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 或监考人员进行反馈。

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

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

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

相关文章

Android中Service在新进程中的启动流程2

目录 1、Service在客户端的启动入口 2、Service启动在AMS的处理 3、Service在新进程中的启动 4、Service与AMS的关系再续 上一篇文章中我们了解了Service在新进程中启动的大致流程&#xff0c;同时认识了与客户端进程交互的接口IApplicationThread以及与AMS交互的接口IActi…

Three城市引擎地图插件Geo-3d

一、简介 基于Three开发&#xff0c;为Three 3D场景提供GIS能力和城市底座渲染能力。支持Web墨卡托、WGS84、GCJ02等坐标系&#xff0c;支持坐标转换&#xff0c;支持影像、地形、geojson建筑、道路&#xff0c;植被等渲染。支持自定义主题。 二、效果 三、代码 //插件初始化…

Ubuntu环境 nginx 源码 编译安装

ubuntu 终端 使用 wget 下载源码 sudo wget http://nginx.org/download/nginx-1.24.0.tar.gz解压刚下载的源码压缩包 nginx-1.24.0.tar.gz sudo tar -zxvf nginx-1.24.0.tar.gz 解压完成 产生 nginx-1.24.0 目录 进入该目录 cd ./nginx-1.24.0 目录下有一个可执行文件 con…

【深度学习】神经网络实战分类与回归任务

第一步 读取数据 ①导入torch import torch ②使用魔法命令&#xff0c;使它使得生成的图形直接嵌入到 Notebook 的单元格输出中&#xff0c;而不是弹出新的窗口来显示图形 %matplotlib inline③读取文件 from pathlib import Path import requestsDATA_PATHPath("dat…

60,【1】BUUCF web [RCTF2015]EasySQL1

先查看源码 1&#xff0c;changepwd&#xff08;修改密码&#xff09; <?php // 开启会话&#xff0c;以便使用会话变量 session_start();// 设置页面的内容类型为 HTML 并使用 UTF-8 编码 header("Content-Type: text/html; charsetUTF-8");// 引入配置文件&…

Chrome插件:图片缩放为头像(128*128)

前置条件&#xff1a; 安装有chrome谷歌浏览器的电脑 使用步骤&#xff1a; 1.打开chrome扩展插件 2.点击管理扩展程序 3.加载已解压的扩展程序 4.选择对应文件夹 5.成功后会出现一个扩展小程序 6.点击对应小程序 7.使用小程序 8.拖拽成功后会自动保存到下载 代码&#xf…

machine learning knn算法之使用KNN对鸢尾花数据集进行分类

通过导入必要的scikit-learn导入必要的库&#xff0c;加载给定的数据&#xff0c;划分测试集和训练集之后训练预测和评估即可 具体代码如下&#xff1a; import numpy as np from sklearn.datasets import load_iris from sklearn.model_selection import train_test_split f…

电子应用设计方案102:智能家庭AI鱼缸系统设计

智能家庭 AI 鱼缸系统设计 一、引言 智能家庭 AI 鱼缸系统旨在为鱼类提供一个健康、舒适的生活环境&#xff0c;同时为用户提供便捷的管理和观赏体验。 二、系统概述 1. 系统目标 - 自动维持水质稳定&#xff0c;包括水温、酸碱度、硬度和溶氧量等关键指标。 - 智能投食&…

【C语言系列】深入理解指针(3)

深入理解指针&#xff08;3&#xff09; 一、字符指针变量二、数组指针变量2.1数组指针变量是什么&#xff1f;2.2数组指针变量怎么初始化&#xff1f; 三、二维数组传参的本质四、函数指针变量4.1函数指针变量的创建4.2函数指针变量的使用4.3两段有趣的代码4.4 typedef关键字 …

2024年度总结-CSDN

2024年CSDN年度总结 Author&#xff1a;OnceDay Date&#xff1a;2025年1月21日 一位热衷于Linux学习和开发的菜鸟&#xff0c;试图谱写一场冒险之旅&#xff0c;也许终点只是一场白日梦… 漫漫长路&#xff0c;有人对你微笑过嘛… 文章目录 2024年CSDN年度总结1. 整体回顾2…

Linux下php8安装phpredis扩展的方法

Linux下php8安装phpredis扩展的方法 下载redis扩展执行安装编辑php.ini文件重启php-fpmphpinfo 查看 下载redis扩展 前提是已经安装好redis服务了 php-redis下载地址 https://github.com/phpredis/phpredis 执行命令 git clone https://github.com/phpredis/phpredis.git执行…

我的2024年度历程回顾

一、自我介绍 这个是我的 个人主页 &#xff1a; zxctscl 从2023年到现在一些小成就 我主要分享的文章是C语言和C方面&#xff1a; 当然也有不少算法题&#xff1a; 二、年度回顾 在过去的一年里&#xff0c;也有不少收获&#xff1a; 在C编程语言的学习方面取得了显著…

AIGC专栏18——EasyAnimateV5.1版本详解 应用Qwen2 VL作为文本编码器,支持轨迹控制与相机镜头控制

AIGC专栏18——EasyAnimateV5.1版本详解 应用Qwen2 VL作为文本编码器&#xff0c;支持轨迹控制与相机镜头控制 学习前言相关地址汇总源码下载地址HF测试链接MS测试链接 测试效果Image to VideoText to Video轨迹控制镜头控制 EasyAnimate详解技术储备Qwen2 VLStable Diffusion …

YOLOv8改进,YOLOv8检测头融合DSConv(动态蛇形卷积),并添加小目标检测层(四头检测),适合目标检测、分割等

精确分割拓扑管状结构例如血管和道路,对各个领域至关重要,可确保下游任务的准确性和效率。然而,许多因素使任务变得复杂,包括细小脆弱的局部结构和复杂多变的全局形态。在这项工作中,注意到管状结构的特殊特征,并利用这一知识来引导 DSCNet 在三个阶段同时增强感知:特征…

U3D的.Net学习

Mono&#xff1a;这是 Unity 最初采用的方式&#xff0c;它将 C# 代码编译为中间语言 (IL)&#xff0c;然后在目标平台上使用虚拟机 (VM) 将其转换为本地机器码执行。 IL2CPP&#xff1a;这是一种较新的方法&#xff0c;它会将 C# 代码先编译为 C 代码&#xff0c;再由 C 编译器…

【MySQL】 库的操作

欢迎拜访&#xff1a;雾里看山-CSDN博客 本篇主题&#xff1a;【MySQL】 库的操作 发布时间&#xff1a;2025.1.23 隶属专栏&#xff1a;MySQL 目录 库的创建语法使用 编码规则认识编码集查看数据库默认的编码集和校验集查看数据库支持的编码集和校验集指定编码创建数据库验证不…

【随手笔记】FFT资料整理

&#xff08;一&#xff09;结果验证 函数波形示例1 #define Fs 44800 #define NPT 256 void InitBufInArray() {int i 0;float fx 0;for(i0; i<NPT; i){// fx 1500 * sin(2*PI * i * 350.0 / Fs) // 2700 * sin(2*PI * i * 8400.0 / Fs) // 4000 * sin(2*P…

Spark Streaming编程基础

文章目录 1. 流式词频统计1.1 Spark Streaming编程步骤1.2 流式词频统计项目1.2.1 创建项目1.2.2 添加项目依赖1.2.3 修改源目录1.2.4 添加scala-sdk库1.2.5 创建日志属性文件 1.3 创建词频统计对象1.4 利用nc发送数据1.5 启动应用&#xff0c;查看结果 2. 编程模型的基本概念3…

R语言学习笔记之开发环境配置

一、概要 整个安装过程及遇到的问题记录 操作步骤备注&#xff08;包含遇到的问题&#xff09;1下载安装R语言2下载安装RStudio3离线安装pacman提示需要安装Rtools4安装Rtoolspacman、tidyfst均离线安装完成5加载tidyfst报错 提示需要安装依赖&#xff0c;试错逐步下载并安装…

【29】Word:李楠-学术期刊❗

目录 题目​ NO1.2.3.4.5 NO6.7.8 NO9.10.11 NO12.13.14.15 NO16 题目 NO1.2.3.4.5 另存为手动/F12Fn光标来到开头位置处→插入→封面→选择花丝→根据样例图片&#xff0c;对应位置填入对应文字 (手动调整即可&#xff09;复制样式&#xff1a;开始→样式对话框→管理…