【2024年华为OD机试】 (C卷,100分)- 字符串排序(Java & JS & Python&C/C++)

一、问题描述

题目描述

排序规则:

  • 单词中字母比较不区分大小写。
  • 两个单词先以第一个字母作为排序的基准,如果第一个字母相同,就用第二个字母为基准,如果第二个字母相同就以第三个字母为基准。依此类推,如果到某个字母不相同,字母顺序在前的那个单词顺序在前。
  • 当一个短单词和一个长单词的开头部分都相同(即短单词是长单词从首字母开始的一部分),短单词顺序在前。
  • 字母大小写不同的相同单词,只输出一次。

输入描述

输出描述

用例

用例 1

输入:

Hello hello world

输出:

Hello world
用例 2

输入:

i LOVE Cc I love CC Hello Hel Hellow

输出:

Cc Hel Hello Hellow i LOVE

题目解析

这题有两部分逻辑,一个是排序,一个是去重。

我这里是先排序后去重,因为我想基于栈结构去重,即排序后,不区分大小写的两个字符串一定是紧挨着的,因此后入栈的字符串如果和栈顶字符串相同(不区分大小写),则不入栈。

排序规则其实就是字典序。但是需要注意的是,不区分大小写排序,因此我们不能直接使用 Array.prototype.sort 的原生字典序排序,而是需要自定义不区分大小写的字典序排序。

详细步骤

  1. 读取输入

    • 从标准输入读取一个字符串,表示单词列表。
  2. 分割单词

    • 使用 split(' ') 方法将字符串按空格分割成单词数组。
  3. 自定义排序

    • 使用 Array.prototype.sort 方法对单词数组进行排序。
    • 自定义排序函数,比较两个单词时,先将它们转换为小写,然后按字典序排序。
  4. 去重

    • 使用栈结构进行去重。
    • 遍历排序后的单词数组,将每个单词尝试压入栈中。
    • 如果栈顶单词与当前单词相同(不区分大小写),则不压入栈中。
  5. 输出结果

    • 使用 Array.prototype.join 方法将栈中的单词拼接成一个字符串并输出。

用例解释

用例 1
  • 输入:
    • Hello hello world
  • 输出:
    • Hello world

解释

  • 排序后的单词列表:['Hello', 'hello', 'world']
  • 去重后的单词列表:['Hello', 'world']
用例 2
  • 输入:
    • i LOVE Cc I love CC Hello Hel Hellow
  • 输出:
    • Cc Hel Hello Hellow i LOVE

解释

  • 排序后的单词列表:['Cc', 'CC', 'Hel', 'Hello', 'Hellow', 'i', 'I', 'LOVE', 'love']
  • 去重后的单词列表:['Cc', 'Hel', 'Hello', 'Hellow', 'i', 'LOVE']

通过上述步骤,我们可以高效地对单词进行排序和去重,确保结果符合要求。这种方法的时间复杂度主要由排序操作决定,为 O(n log n),其中 n 是单词的个数。

二、JavaScript算法源码

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


JavaScript代码

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

const rl = readline.createInterface({
  input: process.stdin,  // 设置输入流为标准输入
  output: process.stdout,  // 设置输出流为标准输出
});

// 监听控制台的输入事件
rl.on("line", (line) => {
  const arr = line.split(" ");  // 将输入的字符串按空格分割成数组

  console.log(sortStr(arr));  // 调用sortStr函数并输出结果
});

// 定义sortStr函数,用于对字符串数组进行排序和去重
function sortStr(arr) {
  // 对数组进行排序
  arr.sort((a, b) => {
    a = a.toLowerCase();  // 将字符串a转换为小写
    b = b.toLowerCase();  // 将字符串b转换为小写

    // 比较两个字符串的大小
    return a === b ? 0 : a > b ? 1 : -1;
  });

  const stack = [arr.shift()];  // 创建一个栈,并将排序后的第一个元素放入栈中

  // 遍历数组,进行去重操作
  for (let str of arr) {
    const top = stack.at(-1).toLowerCase();  // 获取栈顶元素并转换为小写
    const add = str.toLowerCase();  // 获取当前元素并转换为小写
    if (top === add) continue;  // 如果栈顶元素与当前元素相同,跳过
    stack.push(str);  // 否则将当前元素压入栈中
  }

  return stack.join(" ");  // 将栈中的元素用空格连接成字符串并返回
}

代码讲解

  1. 引入模块

    • const readline = require("readline");:引入readline模块,用于读取控制台输入。
  2. 创建接口

    • const rl = readline.createInterface({ input: process.stdin, output: process.stdout });:创建一个readline接口,设置输入流为标准输入,输出流为标准输出。
  3. 监听输入事件

    • rl.on("line", (line) => { ... });:监听控制台的输入事件,当用户输入一行内容时触发回调函数。
    • const arr = line.split(" ");:将输入的字符串按空格分割成数组。
    • console.log(sortStr(arr));:调用sortStr函数并输出结果。
  4. sortStr 函数

    • 排序
      • arr.sort((a, b) => { ... });:对数组进行排序。
      • a = a.toLowerCase();b = b.toLowerCase();:将字符串转换为小写,确保排序时不区分大小写。
      • return a === b ? 0 : a > b ? 1 : -1;:比较两个字符串的大小,返回排序结果。
    • 去重
      • const stack = [arr.shift()];:创建一个栈,并将排序后的第一个元素放入栈中。
      • for (let str of arr) { ... }:遍历数组,进行去重操作。
      • const top = stack.at(-1).toLowerCase();:获取栈顶元素并转换为小写。
      • const add = str.toLowerCase();:获取当前元素并转换为小写。
      • if (top === add) continue;:如果栈顶元素与当前元素相同,跳过。
      • stack.push(str);:否则将当前元素压入栈中。
    • 返回结果
      • return stack.join(" ");:将栈中的元素用空格连接成字符串并返回。

代码功能总结

  • 该程序的功能是:从控制台读取一行字符串,按空格分割成数组,对数组中的字符串进行排序(不区分大小写),并去除重复元素,最后将结果用空格连接成字符串输出。

示例

假设输入字符串为"apple Banana apple orange banana"

  1. 将字符串按空格分割成数组:["apple", "Banana", "apple", "orange", "banana"]
  2. 对数组进行排序(不区分大小写):["apple", "apple", "Banana", "banana", "orange"]
  3. 去重:["apple", "Banana", "orange"]
  4. 将结果用空格连接成字符串:"apple Banana orange"

因此,程序输出为"apple Banana orange"


注意事项

  1. 大小写不敏感排序
    • 在排序时,将字符串转换为小写进行比较,确保排序结果不区分大小写。
  2. 去重逻辑
    • 去重时,仅比较栈顶元素与当前元素,确保相邻的重复元素被去除。
  3. 栈的使用
    • 使用栈来存储去重后的结果,是一种常见的去重方法。

希望这个解释对您理解代码有所帮助!

三、Java算法源码

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


Java代码

import java.util.Arrays;  // 引入Arrays类,用于数组操作
import java.util.LinkedList;  // 引入LinkedList类,用于实现栈
import java.util.Scanner;  // 引入Scanner类,用于读取控制台输入
import java.util.StringJoiner;  // 引入StringJoiner类,用于拼接字符串

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

    String[] arr = sc.nextLine().split(" ");  // 读取一行输入,并按空格分割成字符串数组

    System.out.println(getResult(arr));  // 调用getResult函数并输出结果
  }

  // 算法入口,对字符串数组进行排序和去重
  public static String getResult(String[] arr) {
    // 对数组进行排序(不区分大小写)
    Arrays.sort(arr, (a, b) -> a.toLowerCase().compareTo(b.toLowerCase()));

    // 创建一个栈(使用LinkedList实现),并将排序后的第一个元素放入栈中
    LinkedList<String> stack = new LinkedList<>();
    stack.add(arr[0]);

    // 遍历数组,进行去重操作
    for (int i = 1; i < arr.length; i++) {
      String s = arr[i];  // 获取当前元素
      String top = stack.getLast().toLowerCase();  // 获取栈顶元素并转换为小写
      String add = s.toLowerCase();  // 获取当前元素并转换为小写
      if (top.equals(add)) continue;  // 如果栈顶元素与当前元素相同,跳过
      stack.add(s);  // 否则将当前元素压入栈中
    }

    // 使用StringJoiner将栈中的元素用空格连接成字符串
    StringJoiner sj = new StringJoiner(" ");
    for (String s : stack) sj.add(s);
    return sj.toString();  // 返回拼接后的字符串
  }
}

代码讲解

  1. 引入类库

    • import java.util.Arrays;:引入Arrays类,用于数组操作(如排序)。
    • import java.util.LinkedList;:引入LinkedList类,用于实现栈。
    • import java.util.Scanner;:引入Scanner类,用于读取控制台输入。
    • import java.util.StringJoiner;:引入StringJoiner类,用于拼接字符串。
  2. 主函数 main

    • Scanner sc = new Scanner(System.in);:创建Scanner对象,用于读取控制台输入。
    • String[] arr = sc.nextLine().split(" ");:读取一行输入,并按空格分割成字符串数组。
    • System.out.println(getResult(arr));:调用getResult函数并输出结果。
  3. getResult 函数

    • 排序
      • Arrays.sort(arr, (a, b) -> a.toLowerCase().compareTo(b.toLowerCase()));:对数组进行排序,排序时不区分大小写。
    • 去重
      • LinkedList stack = new LinkedList<>();:创建一个栈(使用LinkedList实现)。
      • stack.add(arr[0]);:将排序后的第一个元素放入栈中。
      • for (int i = 1; i < arr.length; i++) { ... }:遍历数组,进行去重操作。
      • String top = stack.getLast().toLowerCase();:获取栈顶元素并转换为小写。
      • String add = s.toLowerCase();:获取当前元素并转换为小写。
      • if (top.equals(add)) continue;:如果栈顶元素与当前元素相同,跳过。
      • stack.add(s);:否则将当前元素压入栈中。
    • 拼接结果
      • StringJoiner sj = new StringJoiner(" ");:创建StringJoiner对象,用于拼接字符串。
      • for (String s : stack) sj.add(s);:将栈中的元素逐个添加到StringJoiner中。
      • return sj.toString();:返回拼接后的字符串。

代码功能总结

  • 该程序的功能是:从控制台读取一行字符串,按空格分割成数组,对数组中的字符串进行排序(不区分大小写),并去除重复元素,最后将结果用空格连接成字符串输出。

示例

假设输入字符串为"apple Banana apple orange banana"

  1. 将字符串按空格分割成数组:["apple", "Banana", "apple", "orange", "banana"]
  2. 对数组进行排序(不区分大小写):["apple", "apple", "Banana", "banana", "orange"]
  3. 去重:["apple", "Banana", "orange"]
  4. 将结果用空格连接成字符串:"apple Banana orange"

因此,程序输出为"apple Banana orange"


注意事项

  1. 大小写不敏感排序
    • 在排序时,将字符串转换为小写进行比较,确保排序结果不区分大小写。
  2. 去重逻辑
    • 去重时,仅比较栈顶元素与当前元素,确保相邻的重复元素被去除。
  3. 栈的使用
    • 使用LinkedList实现栈,是一种常见的去重方法。
  4. 字符串拼接
    • 使用StringJoiner拼接字符串,可以避免手动处理空格。

希望这个解释对您理解代码有所帮助!

四、Python算法源码

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


Python代码

# 输入获取
arr = input().split()  # 读取一行输入,并按空格分割成列表


# 算法入口
def getResult():
    # 对列表进行排序(不区分大小写)
    arr.sort(key=lambda x: x.lower())

    # 创建一个栈,并将排序后的第一个元素放入栈中
    stack = [arr[0]]

    # 遍历列表,进行去重操作
    for i in range(1, len(arr)):
        s = arr[i]  # 获取当前元素
        top = stack[-1].lower()  # 获取栈顶元素并转换为小写
        add = s.lower()  # 获取当前元素并转换为小写
        if top == add:  # 如果栈顶元素与当前元素相同,跳过
            continue
        stack.append(s)  # 否则将当前元素压入栈中

    # 将栈中的元素用空格连接成字符串并返回
    return " ".join(stack)


# 算法调用
print(getResult())  # 调用getResult函数并输出结果

代码讲解

  1. 输入获取

    • arr = input().split():读取一行输入,并按空格分割成列表。
  2. getResult 函数

    • 排序
      • arr.sort(key=lambda x: x.lower()):对列表进行排序,排序时不区分大小写。
    • 去重
      • stack = [arr[0]]:创建一个栈,并将排序后的第一个元素放入栈中。
      • for i in range(1, len(arr)): ...:遍历列表,进行去重操作。
      • top = stack[-1].lower():获取栈顶元素并转换为小写。
      • add = s.lower():获取当前元素并转换为小写。
      • if top == add: continue:如果栈顶元素与当前元素相同,跳过。
      • stack.append(s):否则将当前元素压入栈中。
    • 拼接结果
      • return " ".join(stack):将栈中的元素用空格连接成字符串并返回。
  3. 算法调用

    • print(getResult()):调用getResult函数并输出结果。

代码功能总结

  • 该程序的功能是:从控制台读取一行字符串,按空格分割成列表,对列表中的字符串进行排序(不区分大小写),并去除重复元素,最后将结果用空格连接成字符串输出。

示例

假设输入字符串为"apple Banana apple orange banana"

  1. 将字符串按空格分割成列表:["apple", "Banana", "apple", "orange", "banana"]
  2. 对列表进行排序(不区分大小写):["apple", "apple", "Banana", "banana", "orange"]
  3. 去重:["apple", "Banana", "orange"]
  4. 将结果用空格连接成字符串:"apple Banana orange"

因此,程序输出为"apple Banana orange"


注意事项

  1. 大小写不敏感排序
    • 在排序时,将字符串转换为小写进行比较,确保排序结果不区分大小写。
  2. 去重逻辑
    • 去重时,仅比较栈顶元素与当前元素,确保相邻的重复元素被去除。
  3. 栈的使用
    • 使用列表实现栈,是一种常见的去重方法。
  4. 字符串拼接
    • 使用" ".join(stack)拼接字符串,可以避免手动处理空格。

希望这个解释对您理解代码有所帮助!

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

以下是 C++代码C语言代码 的实现,并附上详细的中文注释和讲解:


C++代码

#include 
#include 
#include 
#include 

using namespace std;

// 算法入口
string getResult(vector<string>& arr) {
    // 对数组进行排序(不区分大小写)
    sort(arr.begin(), arr.end(), [](const string& a, const string& b) {
        string lowerA = a;
        string lowerB = b;
        transform(lowerA.begin(), lowerA.end(), lowerA.begin(), ::tolower);
        transform(lowerB.begin(), lowerB.end(), lowerB.begin(), ::tolower);
        return lowerA < lowerB;
    });

    // 创建一个栈,并将排序后的第一个元素放入栈中
    vector<string> stack;
    stack.push_back(arr[0]);

    // 遍历数组,进行去重操作
    for (int i = 1; i < arr.size(); i++) {
        string s = arr[i];  // 获取当前元素
        string top = stack.back();  // 获取栈顶元素
        // 将栈顶元素和当前元素转换为小写进行比较
        transform(top.begin(), top.end(), top.begin(), ::tolower);
        string add = s;
        transform(add.begin(), add.end(), add.begin(), ::tolower);
        if (top == add) continue;  // 如果栈顶元素与当前元素相同,跳过
        stack.push_back(s);  // 否则将当前元素压入栈中
    }

    // 将栈中的元素用空格连接成字符串
    stringstream result;
    for (int i = 0; i < stack.size(); i++) {
        if (i > 0) result << " ";  // 添加空格分隔符
        result << stack[i];
    }
    return result.str();  // 返回拼接后的字符串
}

int main() {
    string input;
    getline(cin, input);  // 读取一行输入

    // 将输入按空格分割成数组
    vector<string> arr;
    stringstream ss(input);
    string word;
    while (ss >> word) {
        arr.push_back(word);
    }

    // 调用算法并输出结果
    cout << getResult(arr) << endl;

    return 0;
}

C++代码讲解

  1. 输入获取

    • 使用getline(cin, input)读取一行输入。
    • 使用stringstream将输入按空格分割成vector数组。
  2. getResult 函数

    • 排序
      • 使用sort函数对数组进行排序,排序时不区分大小写。
      • 通过transform函数将字符串转换为小写进行比较。
    • 去重
      • 使用vector实现栈。
      • 遍历数组,比较栈顶元素与当前元素(转换为小写),如果相同则跳过,否则压入栈中。
    • 拼接结果
      • 使用stringstream将栈中的元素用空格连接成字符串。
  3. 主函数

    • 调用getResult函数并输出结果。

C语言代码

#include 
#include 
#include 
#include 

// 比较函数,用于排序(不区分大小写)
int compare(const void* a, const void* b) {
    char* strA = *(char**)a;
    char* strB = *(char**)b;
    char lowerA[100], lowerB[100];
    // 将字符串转换为小写
    for (int i = 0; strA[i]; i++) lowerA[i] = tolower(strA[i]);
    for (int i = 0; strB[i]; i++) lowerB[i] = tolower(strB[i]);
    return strcmp(lowerA, lowerB);
}

// 算法入口
char* getResult(char** arr, int size) {
    // 对数组进行排序(不区分大小写)
    qsort(arr, size, sizeof(char*), compare);

    // 创建一个栈,并将排序后的第一个元素放入栈中
    char** stack = (char**)malloc(size * sizeof(char*));
    int stackSize = 0;
    stack[stackSize++] = arr[0];

    // 遍历数组,进行去重操作
    for (int i = 1; i < size; i++) {
        char* s = arr[i];  // 获取当前元素
        char* top = stack[stackSize - 1];  // 获取栈顶元素
        // 将栈顶元素和当前元素转换为小写进行比较
        char lowerTop[100], lowerS[100];
        for (int j = 0; top[j]; j++) lowerTop[j] = tolower(top[j]);
        for (int j = 0; s[j]; j++) lowerS[j] = tolower(s[j]);
        if (strcmp(lowerTop, lowerS) == 0) continue;  // 如果栈顶元素与当前元素相同,跳过
        stack[stackSize++] = s;  // 否则将当前元素压入栈中
    }

    // 计算结果字符串的长度
    int resultLength = 0;
    for (int i = 0; i < stackSize; i++) {
        resultLength += strlen(stack[i]);
        if (i < stackSize - 1) resultLength += 1;  // 添加空格
    }

    // 分配内存并拼接结果字符串
    char* result = (char*)malloc((resultLength + 1) * sizeof(char));
    int index = 0;
    for (int i = 0; i < stackSize; i++) {
        strcpy(result + index, stack[i]);
        index += strlen(stack[i]);
        if (i < stackSize - 1) result[index++] = ' ';  // 添加空格
    }
    result[index] = '\0';  // 添加字符串结束符

    free(stack);  // 释放栈的内存
    return result;
}

int main() {
    char input[1000];
    fgets(input, sizeof(input), stdin);  // 读取一行输入

    // 将输入按空格分割成数组
    char* arr[100];
    int size = 0;
    char* token = strtok(input, " \n");
    while (token != NULL) {
        arr[size++] = token;
        token = strtok(NULL, " \n");
    }

    // 调用算法并输出结果
    char* result = getResult(arr, size);
    printf("%s\n", result);

    free(result);  // 释放结果字符串的内存
    return 0;
}

C语言代码讲解

  1. 输入获取

    • 使用fgets读取一行输入。
    • 使用strtok将输入按空格分割成字符串数组。
  2. getResult 函数

    • 排序
      • 使用qsort函数对数组进行排序,排序时不区分大小写。
      • 通过tolower函数将字符串转换为小写进行比较。
    • 去重
      • 使用动态数组实现栈。
      • 遍历数组,比较栈顶元素与当前元素(转换为小写),如果相同则跳过,否则压入栈中。
    • 拼接结果
      • 计算结果字符串的长度,分配内存并拼接字符串。
  3. 主函数

    • 调用getResult函数并输出结果。
    • 释放动态分配的内存。

代码功能总结

  • 该程序的功能是:从控制台读取一行字符串,按空格分割成数组,对数组中的字符串进行排序(不区分大小写),并去除重复元素,最后将结果用空格连接成字符串输出。

示例

假设输入字符串为"apple Banana apple orange banana"

  1. 将字符串按空格分割成数组:["apple", "Banana", "apple", "orange", "banana"]
  2. 对数组进行排序(不区分大小写):["apple", "apple", "Banana", "banana", "orange"]
  3. 去重:["apple", "Banana", "orange"]
  4. 将结果用空格连接成字符串:"apple Banana orange"

因此,程序输出为"apple Banana orange"


希望这个解释对您理解代码有所帮助!

你可能感兴趣的:(华为od,c语言,java,游戏,C++,javascript,python)