目录

题目

思路

Code


题目

通信设备SN一般是包含:字母、数字,用'-'(破折号)进行分组分割,例如:8F-3T-1G-2n是一个有效的SN地址。
现在要对已经存在的SN 按照新的规则进行重排:
输入1:一个有效的SN地址字符串(字符串可以为空,长度小于10000),表示要被重新排列的SN地址;

输入2:给定的一个数字m,1<=m<=10,表示要每个分组恰好包含m个字符,用'-'进行分组分割;
重排规则:
1.如果字母与数字的总和不是m的倍数,则特例(即小于m个字符的分组)放在第一个。
2.将所有的小写字母转换为大写字母。
3.如果出现异常场景,返回空字符串。

样例1

输入

8F-3T-1G-2n
4

输出

8F3T-1G2N
说明

字符串S被分成了两个部分,每部分4个字符;
注意,两个额外的破折号需要删掉。
样例2

输入

2-2g-5-g
2

输出

2-2G-5G

思路

简单题。字符串处理

1. 预处理
将输入的 SN 字符串中所有 - 删除,得到纯字符序列 merged

2. 合法性校验
遍历 merged 每个字符,只允许字母(a-zA-Z)和数字(0-9),否则返回空字符串。

3. 小写转大写
所有字母转为大写。

4. 分组逻辑

  • 设 n = len(merged),若 n = 0 直接返回空字符串。
  • 若 n % m != 0,则第一个分组的长度为 n % m(余数放最前面),后续每组 m 个。
  • 若 n % m == 0,全部按 m 个一组。

5. 结果组装
各组用 - 连接,返回最终字符串。

6. 复杂度
时间 O(n),空间 O(n),n ≤ 10000。

Code

import sys


def solve(sn, m):
    """
    SN 地址重排核心算法
    :param sn: 原始 SN 字符串(可能包含破折号)
    :param m:   每个分组的字符数
    :return:    重排后的 SN 字符串,异常场景返回空字符串
    """
    # ---- 参数合法性校验 ----
    # m 必须为正整数(1 ≤ m ≤ 10),m <= 0 属于异常场景,直接返回空
    if m <= 0:
        return ""

    # ---- 第 1 步:移除所有破折号,得到纯字母数字序列 ----
    # 例如 "8F-3T-1G-2n" -> "8F3T1G2n"
    merged = sn.replace('-', '')

    # ---- 第 2 步:空字符串处理 ----
    # 移除破折号后如果为空(原始字符串为空或只有破折号),返回空字符串
    if not merged:
        return ""

    # ---- 第 3 步:字符合法性校验 ----
    # SN 中只允许字母(a-z A-Z)和数字(0-9),出现其他字符视为异常场景
    for ch in merged:
        if not (ch.isdigit() or ch.isalpha()):
            return ""

    # ---- 第 4 步:小写字母转大写 ----
    # 将所有小写字母统一转换为大写形式
    merged = merged.upper()

    n = len(merged)

    # ---- 第 5 步:按规则分组 ----
    # 规则 1:如果总长度 n 不是 m 的倍数,余数 r = n % m 的部分作为第一个分组
    #         (即"余数在前"),后续每组恰好 m 个字符
    # 规则 2:每组之间用 '-' 连接
    groups = []
    pos = 0

    # 先处理余数部分(如果存在)
    r = n % m
    if r != 0:
        groups.append(merged[:r])   # 前 r 个字符为第一个分组
        pos = r                      # 游标移动到 r 位置

    # 后续每 m 个字符为一组,直到字符串末尾
    while pos < n:
        groups.append(merged[pos:pos + m])
        pos += m

    # 用 '-' 将所有分组连接成最终的 SN 字符串
    return '-'.join(groups)


def main():
    """
    主函数:从标准输入读取两行数据,调用 solve 函数处理后输出
    异常场景:任何异常(I/O 错误、格式错误等)都输出空行
    """
    try:
        # 读取第一行:SN 字符串
        # rstrip('\n\r') 去除末尾的换行符(兼容 Windows CRLF 和 Linux LF)
        sn = sys.stdin.readline().rstrip('\n\r')

        # 读取第二行:分组数 m
        # 跳过可能的空行,找到第一个非空行作为 m
        m = 0
        while True:
            line = sys.stdin.readline()
            if not line:          # 读到文件末尾仍未找到 m,退出循环
                break
            line = line.strip()   # 去除首尾空白字符
            if line:               # 非空行,即为 m 的值
                m = int(line)
                break

        # 调用核心求解函数并输出结果
        print(solve(sn, m))
    except Exception:
        # 任何异常场景(如 int() 转换失败等),输出空行
        print()


if __name__ == "__main__":
    main()

JS

const readline = require('readline');

/**
 * SN 地址重排核心算法
 * @param {string} sn 原始 SN 字符串(可能包含破折号)
 * @param {number} m  每个分组的字符数
 * @returns {string}  重排后的 SN 字符串,异常场景返回空字符串
 */
function solve(sn, m) {
    // ---- 参数合法性校验 ----
    // m 必须为正整数(1 ≤ m ≤ 10),m <= 0 属于异常场景,直接返回空
    if (m <= 0) return '';

    // ---- 第 1 步:移除所有破折号,得到纯字母数字序列 ----
    // 例如 "8F-3T-1G-2n" -> "8F3T1G2n"
    let merged = sn.replace(/-/g, '');

    // ---- 第 2 步:空字符串处理 ----
    // 移除破折号后如果为空(原始字符串为空或只有破折号),返回空字符串
    if (!merged) return '';

    // ---- 第 3 步:字符合法性校验 ----
    // SN 中只允许字母(a-z A-Z)和数字(0-9),出现其他字符视为异常场景
    for (const ch of merged) {
        if (!/[a-zA-Z0-9]/.test(ch)) return '';
    }

    // ---- 第 4 步:小写字母转大写 ----
    merged = merged.toUpperCase();

    const n = merged.length;

    // ---- 第 5 步:按规则分组 ----
    // 规则 1:如果总长度 n 不是 m 的倍数,余数 r = n % m 的部分作为第一个分组
    //         (即"余数在前"),后续每组恰好 m 个字符
    // 规则 2:每组之间用 '-' 连接
    const groups = [];
    let pos = 0;

    // 先处理余数部分(如果存在)
    const r = n % m;
    if (r !== 0) {
        groups.push(merged.substring(0, r));  // 前 r 个字符为第一个分组
        pos = r;                              // 游标移动到 r 位置
    }

    // 后续每 m 个字符为一组,直到字符串末尾
    while (pos < n) {
        groups.push(merged.substring(pos, pos + m));
        pos += m;
    }

    // 用 '-' 将所有分组连接成最终的 SN 字符串
    return groups.join('-');
}

// ---- 主程序:读取标准输入,处理并输出结果 ----

// 创建 readline 接口,逐行读取标准输入
const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});

let firstLine = true;   // 是否正在读取第一行(SN 字符串)
let sn;                 // 存储第一行读取到的 SN 字符串
let processed = false;  // 标记是否已正常处理完成,防止 close 事件重复输出

// 监听每一行输入
rl.on('line', (line) => {
    try {
        if (firstLine) {
            // 第一行:读取 SN 字符串
            sn = line;
            firstLine = false;
        } else {
            // 第二行:读取分组数 m
            // 去除首尾空白后取非空行
            const trimmed = line.trim();
            if (trimmed !== '') {
                const m = parseInt(trimmed, 10);  // 解析整数
                console.log(solve(sn, m));         // 输出重排结果
                processed = true;                  // 标记处理完成
                rl.close();                        // 关闭输入流
            }
        }
    } catch (e) {
        // 异常场景:任何运行时异常都输出空行
        if (!processed) {
            console.log('');
            processed = true;
        }
        rl.close();
    }
});

// 处理只有一行输入(缺少 m)的边界情况
rl.on('close', () => {
    // 如果已经正常处理过(processed = true)则不再输出
    if (!processed && !firstLine && sn !== undefined) {
        console.log('');
    }
});

【华为od机试真题Python+JS+Java+Go合集】【超值优惠】:Py/JS/Java/Go合集

【华为od机试真题Python】:Python真题题库

【华为od机试真题JavaScript】:JavaScript真题题库

【华为od机试真题Java&Go】:Java&Go真题题库

【华为od机试真题C++】:C++真题题库

【华为od机试真题C语言】:C语言真题题库

【华为od面试手撕代码题库】:面试手撕代码题库

【华为od机试面试交流群】【文章底部有二维码链接,可扫码加交流群】

华为OD机试:二本院校有机会吗?
有机会,但不大,大神除外!机考分数越高越好,所以需要提前刷题。机考通过后,如果没有收到面试邀请,也不要着急,非目标院校面试邀请发的时间比较晚。非目标院校今年有点难,机试至少要考到350分,所以需要疯狂刷题,华为OD机考是有题库的,最好在考前完所有题库题目。华为OD机试:跨专业可以参加华为OD可以,但是如果你的本科院校比较差,上岸概率不大。华为OD机试:华为OD简历被锁定机试通过,性格测试也通过,但是没人联系面试,发现简历被锁定。此时需要主动去联系HR。让他帮助你查询原因。

更多推荐