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

一、问题描述

题目描述

小组中每位都有一张卡片,卡片上是6位内的正整数,将卡片连起来可以组成多种数字,计算组成的最大数字。

输入描述

","号分割的多个正整数字符串,不需要考虑非数字异常情况,小组最多25个人。

输出描述

最大的数字字符串

用例

用例 1

输入:

22,221

输出:

22221
用例 2

输入:

4589,101,41425,9999

输出:

9999458941425101

解题思路

  1. 读取输入

    • 从标准输入读取一个字符串,表示小组成员的卡片数字。
  2. 分割字符串

    • 使用 split(',') 方法将字符串按逗号分割成数字数组。
  3. 自定义排序

    • 使用 Array.prototype.sort 方法对数字数组进行排序。
    • 自定义排序函数,对于两个数字 ab,比较 a + bb + a 的大小,较大的排在前面。
  4. 拼接结果

    • 使用 Array.prototype.join 方法将排序后的数字数组拼接成一个字符串。
  5. 输出结果

    • 输出拼接后的字符串。

详细步骤

  1. 读取输入

    • 从标准输入读取一个字符串,表示小组成员的卡片数字。
  2. 分割字符串

    • 使用 split(',') 方法将字符串按逗号分割成数字数组。
  3. 自定义排序

    • 使用 Array.prototype.sort 方法对数字数组进行排序。
    • 自定义排序函数,对于两个数字 ab,比较 a + bb + a 的大小,较大的排在前面。
  4. 拼接结果

    • 使用 Array.prototype.join 方法将排序后的数字数组拼接成一个字符串。
  5. 输出结果

    • 输出拼接后的字符串。

用例解释

用例 1
  • 输入:
    • 22,221
  • 输出:
    • 22221

解释

  • 比较 22 + 221221 + 22 的大小,22221 大于 22122,所以 22 排在前面。
用例 2
  • 输入:
    • 4589,101,41425,9999
  • 输出:
    • 9999458941425101

解释

  • 比较所有可能的组合,最终得到最大的数字组合为 9999458941425101

通过上述步骤,我们可以高效地求出组成的最大数字。这种方法的时间复杂度主要由排序操作决定,为 O(n log n),其中 n 是数字的个数。

二、JavaScript算法源码

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


JavaScript 代码

javascript 复制代码
/* JavaScript Node ACM模式 控制台输入获取 */
const readline = require("readline"); // 引入 readline 模块,用于读取控制台输入

// 创建 readline 接口实例
const rl = readline.createInterface({
  input: process.stdin,  // 输入流为标准输入
  output: process.stdout, // 输出流为标准输出
});

// 监听 'line' 事件,当用户输入一行内容时触发
rl.on("line", (line) => {
  // 将输入的内容按逗号分隔成数组
  const arr = line.split(",");

  // 对数组进行自定义排序
  arr.sort((a, b) => {
    // 将两个字符串拼接成两种可能的组合
    const s1 = a + b; // 组合方式1:a在前,b在后
    const s2 = b + a; // 组合方式2:b在前,a在后

    // 比较两种组合的字典序大小
    if (s1 == s2) {
      return 0; // 如果两种组合相等,返回 0
    } else if (s1 > s2) {
      return -1; // 如果 s1 的字典序更大,返回 -1(表示 a 应该排在 b 前面)
    } else {
      return 1; // 如果 s2 的字典序更大,返回 1(表示 b 应该排在 a 前面)
    }
  });

  // 将排序后的数组拼接成一个字符串并输出
  console.log(arr.join(""));
});

代码逻辑讲解

1. 引入模块
  • const readline = require("readline");:引入 Node.js 的 readline 模块,用于从控制台读取用户输入。
2. 创建 readline 接口
  • rl = readline.createInterface({ input: process.stdin, output: process.stdout });:创建一个 readline 接口实例,绑定标准输入和标准输出。
3. 监听输入事件
  • rl.on("line", (line) => { ... });:监听 line 事件,当用户输入一行内容并按回车键时,触发回调函数。
4. 处理输入内容
  • const arr = line.split(",");:将用户输入的字符串按逗号 , 分隔成一个数组。
    • 例如,输入 "3,30,34,5,9",会得到数组 ["3", "30", "34", "5", "9"]
5. 自定义排序
  • arr.sort((a, b) => { ... });:对数组进行自定义排序。
    • 排序规则 :比较两个字符串的两种拼接方式 a + bb + a,选择字典序更大的组合。
      • 如果 a + b 的字典序更大,则 a 应该排在 b 前面(返回 -1)。
      • 如果 b + a 的字典序更大,则 b 应该排在 a 前面(返回 1)。
      • 如果两者相等,则顺序不变(返回 0)。
6. 输出结果
  • console.log(arr.join(""));:将排序后的数组拼接成一个字符串并输出。
    • 例如,排序后的数组 ["9", "5", "34", "3", "30"] 会拼接成 "9534330"

代码细节解析

1. 输入处理
  • 用户输入的内容是一个以逗号分隔的字符串,例如 "3,30,34,5,9"
  • 使用 split(",") 方法将字符串分割成数组。
2. 自定义排序逻辑
  • 核心思想 :通过比较两种拼接方式的字典序,确定两个字符串的相对顺序。
    • 例如,比较 "3""30"
      • 拼接方式1:"3" + "30" = "330"
      • 拼接方式2:"30" + "3" = "303"
      • 比较 "330""303",发现 "330" 的字典序更大,因此 "3" 应该排在 "30" 前面。
3. 输出结果
  • 使用 join("") 方法将数组拼接成一个字符串。
    • 例如,数组 ["9", "5", "34", "3", "30"] 会拼接成 "9534330"

示例运行

输入
3,30,34,5,9
处理步骤
  1. 将输入字符串分割成数组:
    [
    ["3", "30", "34", "5", "9"]
    ]
  2. 对数组进行自定义排序:
    • 比较 "3""30"
      [
      "330" > "303" \Rightarrow "3" \text{ 排在 } "30" \text{ 前面}
      ]
    • 比较 "34""3"
      [
      "343" > "334" \Rightarrow "34" \text{ 排在 } "3" \text{ 前面}
      ]
    • 比较 "5""9"
      [
      "59" < "95" \Rightarrow "9" \text{ 排在 } "5" \text{ 前面}
      ]
    • 最终排序结果:
      [
      ["9", "5", "34", "3", "30"]
      ]
  3. 将排序后的数组拼接成字符串:
    [
    "9534330"
    ]
输出
9534330

总结

  • 功能:将一组数字字符串拼接成字典序最大的字符串。
  • 核心逻辑:通过自定义排序规则,比较两种拼接方式的字典序。
  • 适用场景:需要将一组数字拼接成最大值的场景,例如生成最大编号、最大金额等。
  • 注意事项
    • 输入的数字字符串可能包含前导零,需要确保排序逻辑正确。
    • 如果输入为空,程序会输出空字符串。

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

三、Java算法源码

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


Java 代码

java 复制代码
import java.util.Arrays;  // 导入 Arrays 工具类,用于数组操作
import java.util.Scanner; // 导入 Scanner 类,用于读取控制台输入

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

    // 读取用户输入的一行内容,并按逗号分隔成字符串数组
    String[] arr = sc.next().split(",");

    // 对数组进行自定义排序
    Arrays.sort(arr, (a, b) -> (b + a).compareTo(a + b));

    // 使用 StringBuilder 拼接排序后的数组元素
    StringBuilder sb = new StringBuilder();
    for (String s : arr) {
      sb.append(s); // 将每个字符串追加到 StringBuilder 中
    }

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

代码逻辑讲解

1. 导入类库
  • import java.util.Arrays;:导入 Arrays 工具类,用于数组操作(如排序)。
  • import java.util.Scanner;:导入 Scanner 类,用于从控制台读取用户输入。
2. 主程序入口
  • public static void main(String[] args):Java 程序的入口方法。
3. 创建 Scanner 对象
  • Scanner sc = new Scanner(System.in);:创建 Scanner 对象,用于读取控制台输入。
4. 读取输入并分割成数组
  • String[] arr = sc.next().split(",");:读取用户输入的一行内容,并按逗号 , 分隔成字符串数组。
    • 例如,输入 "3,30,34,5,9",会得到数组 ["3", "30", "34", "5", "9"]
5. 自定义排序
  • Arrays.sort(arr, (a, b) -> (b + a).compareTo(a + b));:对数组进行自定义排序。
    • 排序规则 :比较两个字符串的两种拼接方式 b + aa + b,选择字典序更大的组合。
      • 如果 b + a 的字典序更大,则 b 应该排在 a 前面。
      • 如果 a + b 的字典序更大,则 a 应该排在 b 前面。
      • 使用 compareTo 方法比较字符串的字典序。
6. 拼接排序后的数组
  • StringBuilder sb = new StringBuilder();:创建 StringBuilder 对象,用于高效拼接字符串。
  • for (String s : arr) { sb.append(s); }:遍历排序后的数组,将每个字符串追加到 StringBuilder 中。
7. 输出结果
  • System.out.println(sb);:输出拼接后的字符串。

代码细节解析

1. 输入处理
  • 用户输入的内容是一个以逗号分隔的字符串,例如 "3,30,34,5,9"
  • 使用 split(",") 方法将字符串分割成数组。
2. 自定义排序逻辑
  • 核心思想 :通过比较两种拼接方式的字典序,确定两个字符串的相对顺序。
    • 例如,比较 "3""30"
      • 拼接方式1:"3" + "30" = "330"
      • 拼接方式2:"30" + "3" = "303"
      • 比较 "303""330",发现 "330" 的字典序更大,因此 "3" 应该排在 "30" 前面。
    • 使用 Lambda 表达式 (a, b) -> (b + a).compareTo(a + b) 实现自定义排序规则。
3. 拼接字符串
  • 使用 StringBuilder 拼接字符串,避免频繁创建字符串对象,提高性能。
4. 输出结果
  • 使用 System.out.println(sb); 输出最终结果。

示例运行

输入
3,30,34,5,9
处理步骤
  1. 将输入字符串分割成数组:
    [
    ["3", "30", "34", "5", "9"]
    ]
  2. 对数组进行自定义排序:
    • 比较 "3""30"
      [
      "303" < "330" \Rightarrow "3" \text{ 排在 } "30" \text{ 前面}
      ]
    • 比较 "34""3"
      [
      "334" < "343" \Rightarrow "34" \text{ 排在 } "3" \text{ 前面}
      ]
    • 比较 "5""9"
      [
      "59" < "95" \Rightarrow "9" \text{ 排在 } "5" \text{ 前面}
      ]
    • 最终排序结果:
      [
      ["9", "5", "34", "3", "30"]
      ]
  3. 将排序后的数组拼接成字符串:
    [
    "9534330"
    ]
输出
9534330

总结

  • 功能:将一组数字字符串拼接成字典序最大的字符串。
  • 核心逻辑:通过自定义排序规则,比较两种拼接方式的字典序。
  • 适用场景:需要将一组数字拼接成最大值的场景,例如生成最大编号、最大金额等。
  • 注意事项
    • 输入的数字字符串可能包含前导零,需要确保排序逻辑正确。
    • 如果输入为空,程序会输出空字符串。

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

四、Python算法源码

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


Python 代码

python 复制代码
import functools  # 导入 functools 模块,用于将比较函数转换为 key 函数

# 输入获取
arr = input().split(",")  # 读取用户输入的一行内容,并按逗号分隔成列表

# 排序规则
def cmp(a, b):
    s1 = a + b  # 拼接方式1:a在前,b在后
    s2 = b + a  # 拼接方式2:b在前,a在后
    return 0 if s1 == s2 else -1 if s1 > s2 else 1  # 比较两种拼接方式的字典序

# 算法入口
def getResult(arr):
    # 使用自定义排序规则对列表进行排序
    arr.sort(key=functools.cmp_to_key(cmp))
    # 将排序后的列表拼接成一个字符串并返回
    return "".join(arr)

# 算法调用
print(getResult(arr))  # 输出最终结果

代码逻辑讲解

1. 导入模块
  • import functools:导入 functools 模块,用于将比较函数转换为 key 函数,以便在排序时使用。
2. 输入处理
  • arr = input().split(","):读取用户输入的一行内容,并按逗号 , 分隔成列表。
    • 例如,输入 "3,30,34,5,9",会得到列表 ["3", "30", "34", "5", "9"]
3. 自定义排序规则
  • def cmp(a, b)::定义一个比较函数 cmp,用于比较两个字符串的拼接方式。
    • 拼接方式1a + ba 在前,b 在后)。
    • 拼接方式2b + ab 在前,a 在后)。
    • 比较逻辑
      • 如果 s1 == s2,返回 0(表示两者相等)。
      • 如果 s1 > s2,返回 -1(表示 a 应该排在 b 前面)。
      • 如果 s1 < s2,返回 1(表示 b 应该排在 a 前面)。
4. 算法入口
  • def getResult(arr)::定义一个函数 getResult,用于对列表进行排序并返回结果。
    • arr.sort(key=functools.cmp_to_key(cmp)):使用自定义排序规则对列表进行排序。
      • functools.cmp_to_key(cmp):将比较函数 cmp 转换为 key 函数,以便在 sort 方法中使用。
    • return "".join(arr):将排序后的列表拼接成一个字符串并返回。
5. 算法调用
  • print(getResult(arr)):调用 getResult 函数并输出结果。

代码细节解析

1. 输入处理
  • 用户输入的内容是一个以逗号分隔的字符串,例如 "3,30,34,5,9"
  • 使用 split(",") 方法将字符串分割成列表。
2. 自定义排序逻辑
  • 核心思想 :通过比较两种拼接方式的字典序,确定两个字符串的相对顺序。
    • 例如,比较 "3""30"
      • 拼接方式1:"3" + "30" = "330"
      • 拼接方式2:"30" + "3" = "303"
      • 比较 "330""303",发现 "330" 的字典序更大,因此 "3" 应该排在 "30" 前面。
3. 排序实现
  • 使用 functools.cmp_to_key(cmp) 将比较函数 cmp 转换为 key 函数,以便在 sort 方法中使用。
  • arr.sort(key=functools.cmp_to_key(cmp)):对列表进行自定义排序。
4. 拼接字符串
  • 使用 "".join(arr) 将排序后的列表拼接成一个字符串。

示例运行

输入
3,30,34,5,9
处理步骤
  1. 将输入字符串分割成列表:
    [
    ["3", "30", "34", "5", "9"]
    ]
  2. 对列表进行自定义排序:
    • 比较 "3""30"
      [
      "330" > "303" \Rightarrow "3" \text{ 排在 } "30" \text{ 前面}
      ]
    • 比较 "34""3"
      [
      "343" > "334" \Rightarrow "34" \text{ 排在 } "3" \text{ 前面}
      ]
    • 比较 "5""9"
      [
      "59" < "95" \Rightarrow "9" \text{ 排在 } "5" \text{ 前面}
      ]
    • 最终排序结果:
      [
      ["9", "5", "34", "3", "30"]
      ]
  3. 将排序后的列表拼接成字符串:
    [
    "9534330"
    ]
输出
9534330

总结

  • 功能:将一组数字字符串拼接成字典序最大的字符串。
  • 核心逻辑:通过自定义排序规则,比较两种拼接方式的字典序。
  • 适用场景:需要将一组数字拼接成最大值的场景,例如生成最大编号、最大金额等。
  • 注意事项
    • 输入的数字字符串可能包含前导零,需要确保排序逻辑正确。
    • 如果输入为空,程序会输出空字符串。

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

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

以下是 C 代码的详细中文注释和逻辑讲解


C 代码

c 复制代码
#include <stdio.h>  // 标准输入输出库
#include <stdlib.h> // 标准库,包含内存分配和排序函数
#include <string.h> // 字符串操作库

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

// 自定义比较函数
int cmp(const void* a, const void* b) {
    char* A = *((char**) a); // 将 void* 转换为 char* 指针
    char* B = *((char**) b); // 将 void* 转换为 char* 指针

    char AB[10000] = {'\0'}; // 初始化拼接字符串 AB
    strcat(AB, A);           // 将 A 拼接到 AB
    strcat(AB, B);           // 将 B 拼接到 AB

    char BA[10000] = {'\0'}; // 初始化拼接字符串 BA
    strcat(BA, B);           // 将 B 拼接到 BA
    strcat(BA, A);           // 将 A 拼接到 BA

    return strcmp(BA, AB);   // 比较 BA 和 AB 的字典序
}

int main() {
    char line[10000];        // 定义输入缓冲区
    gets(line);              // 读取用户输入的一行内容

    char* ss[MAX_SIZE];      // 定义指针数组,用于存储分割后的字符串
    int ss_size = 0;         // 记录分割后的字符串数量

    // 使用 strtok 分割输入字符串
    char* token = strtok(line, ",");
    while (token != NULL) {
        ss[ss_size++] = token; // 将分割后的字符串存入数组
        token = strtok(NULL, ","); // 继续分割
    }

    // 使用 qsort 对字符串数组进行排序
    qsort(ss, ss_size, sizeof(char*), cmp);

    // 定义结果字符串
    char res[10000] = {'\0'};
    for (int i = 0; i < ss_size; i++) {
        strcat(res, ss[i]); // 将排序后的字符串拼接到结果中
    }

    puts(res); // 输出最终结果

    return 0;
}

代码逻辑讲解

1. 头文件引入
  • #include <stdio.h>:标准输入输出库,用于 printfgets 等函数。
  • #include <stdlib.h>:标准库,包含 qsort 等函数。
  • #include <string.h>:字符串操作库,包含 strcatstrcmp 等函数。
2. 定义常量
  • #define MAX_SIZE 25:定义最大数组大小,用于存储分割后的字符串。
3. 自定义比较函数
  • int cmp(const void* a, const void* b):定义比较函数,用于 qsort 排序。
    • 参数abvoid* 类型的指针,指向需要比较的字符串。
    • 逻辑
      1. void* 转换为 char* 指针,获取字符串 AB
      2. 拼接两种方式:
        • ABA + B
        • BAB + A
      3. 使用 strcmp 比较 BAAB 的字典序:
        • 如果 BA > AB,返回正数(B 应该排在 A 前面)。
        • 如果 BA < AB,返回负数(A 应该排在 B 前面)。
        • 如果 BA == AB,返回 0(两者相等)。
4. 主函数
  • 输入处理
    • char line[10000];:定义输入缓冲区。
    • gets(line);:读取用户输入的一行内容。
  • 字符串分割
    • char* ss[MAX_SIZE];:定义指针数组,用于存储分割后的字符串。
    • int ss_size = 0;:记录分割后的字符串数量。
    • 使用 strtok 函数按逗号 , 分割输入字符串:
      • char* token = strtok(line, ",");:首次调用 strtok,获取第一个分割后的字符串。
      • while (token != NULL):循环分割,直到所有字符串被分割完毕。
      • ss[ss_size++] = token;:将分割后的字符串存入数组。
      • token = strtok(NULL, ",");:继续分割下一个字符串。
  • 排序
    • qsort(ss, ss_size, sizeof(char*), cmp);:使用 qsort 对字符串数组进行排序。
      • ss:待排序的数组。
      • ss_size:数组大小。
      • sizeof(char*):每个元素的大小。
      • cmp:自定义比较函数。
  • 拼接结果
    • char res[10000] = {'\0'};:定义结果字符串,初始化为空。
    • 使用 strcat 将排序后的字符串拼接到 res 中。
  • 输出结果
    • puts(res);:输出最终结果。

代码细节解析

1. 输入处理
  • 使用 gets(line); 读取用户输入的一行内容。
  • 使用 strtok 按逗号 , 分割字符串,并将分割后的字符串存入指针数组 ss
2. 自定义排序逻辑
  • 核心思想 :通过比较两种拼接方式的字典序,确定两个字符串的相对顺序。
    • 例如,比较 "3""30"
      • 拼接方式1:"3" + "30" = "330"
      • 拼接方式2:"30" + "3" = "303"
      • 比较 "303""330",发现 "330" 的字典序更大,因此 "3" 应该排在 "30" 前面。
3. 排序实现
  • 使用 qsort 对字符串数组进行排序,排序规则由自定义比较函数 cmp 决定。
4. 拼接字符串
  • 使用 strcat 将排序后的字符串拼接到结果字符串 res 中。

示例运行

输入
3,30,34,5,9
处理步骤
  1. 将输入字符串分割成数组:
    [
    ["3", "30", "34", "5", "9"]
    ]
  2. 对数组进行自定义排序:
    • 比较 "3""30"
      [
      "303" < "330" \Rightarrow "3" \text{ 排在 } "30" \text{ 前面}
      ]
    • 比较 "34""3"
      [
      "334" < "343" \Rightarrow "34" \text{ 排在 } "3" \text{ 前面}
      ]
    • 比较 "5""9"
      [
      "59" < "95" \Rightarrow "9" \text{ 排在 } "5" \text{ 前面}
      ]
    • 最终排序结果:
      [
      ["9", "5", "34", "3", "30"]
      ]
  3. 将排序后的数组拼接成字符串:
    [
    "9534330"
    ]
输出
9534330

总结

  • 功能:将一组数字字符串拼接成字典序最大的字符串。
  • 核心逻辑:通过自定义排序规则,比较两种拼接方式的字典序。
  • 适用场景:需要将一组数字拼接成最大值的场景,例如生成最大编号、最大金额等。
  • 注意事项
    • 输入的数字字符串可能包含前导零,需要确保排序逻辑正确。
    • 如果输入为空,程序会输出空字符串。

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

相关推荐
liuweidong080234 分钟前
【Pandas】pandas Series rtruediv
前端·javascript·pandas
兩尛2 小时前
项目概述、开发环境搭建(day01)
java·spring boot·web
闲人编程2 小时前
PID控制器 (Proportional-Integral-Derivative Controller) 算法详解及案例分析
python·算法·pid·路径规划·微分控制·积分控制·比例控制
我想学LINUX3 小时前
【2024年华为OD机试】(C卷,100分)- 攀登者1 (Java & JS & Python&C/C++)
java·c语言·javascript·c++·python·游戏·华为od
然后就去远行吧4 小时前
小程序组件 —— 31 事件系统 - 事件绑定和事件对象
前端·javascript·小程序
夕阳_醉了4 小时前
如何在JS里进行深拷贝
开发语言·javascript·ecmascript
日暮温柔5 小时前
实现nacos配置修改后无需重启服务--使用@RefreshScope注解
java
疯狂的沙粒6 小时前
对React的高阶组件的理解?应用场景?
前端·javascript·react.js·前端框架
星云code6 小时前
【HM-React】08. Layout模块
javascript·react.js·ecmascript
武昌库里写JAVA6 小时前
React方向:react中5种Dom的操作方式
java·开发语言·spring boot·学习·课程设计