华为机试—字符串排序

题目

对于给定的由可见字符和空格组成的字符串,按照下方的规则进行排序:

  • 按照字母表中的顺序排序(不区分大小写);
  • 同一字母的大小写同时存在时,按照输入顺序排列;
  • 非字母字符保持原来的位置不参与排序;

直接输出排序后的字符串。字符串由 ASCII 码在 32 到 126 范围内的字符组成。

示例

示例1

输入:BabA

输出:aABb

示例2

输入:Hello NowCoder!

输出:CdeeH llNooorw!

分析

为了实现对给定字符串按照指定规则进行排序,可以采用以下思路:

  1. 遍历字符串,提取其中的字母并存储到一个新的容器中
  2. 对存储字母的容器进行排序,排序时不区分大小写
  3. 再次遍历原字符串,将排序后的字母依次放回原字符串中字母的位置,非字母字符保持不变

线性遍历+稳定排序

为了满足 “同一字母的大小写同时存在时,按照输入顺序排列” 这一规则,我们可以使用稳定排序算法来处理提取出的字母。std::stable_sort 可以保证相等元素的相对顺序不变。

时间复杂度:O(n+k\log k),其中 n 是字符串的长度,k 是字符串中字母的数量

空间复杂度:O(k)

#include <bits/stdc++.h>
using namespace std;
// 自定义比较函数,不区分大小写进行比较
bool compare(char a, char b) {
    return tolower(a) < tolower(b);
}
int main() {
    string s;
    // 读取输入的字符串
    getline(cin, s);
    vector<char> letters;
    // 提取字符串中的字母
    for (char c : s) {
        if (isalpha(c)) {
            letters.push_back(c);
        }
    }
    // 使用稳定排序对字母进行排序,不区分大小写
    stable_sort(letters.begin(), letters.end(), compare);
    int letterIndex = 0;
    string result;
    // 构建排序后的字符串
    for (char c : s) {
        if (isalpha(c)) {
            result += letters[letterIndex++];
        } else {
            result += c;
        }
    }
    // 输出排序后的字符串
    cout << result << endl;
    return 0;
}    

知识充电

tolower() 函数

tolower 函数是 C 和 C++ 标准库中的一个字符处理函数,用于将一个字符转换为小写形式。

C 中的 tolower 函数

#include <ctype.h>
int tolower(int c);

C++ 中的 tolower 函数

#include <cctype>
int tolower(int c);

    tolower 函数仅对 ASCII 字符集中的大写字母有效,对于非 ASCII 字符或者非字母字符,它会直接返回原字符。由于返回值类型是 int,在将结果赋值给 char 类型变量时,可能需要进行类型转换。对应的反函数是 toupper 函数。

    isalpha() 函数

    isalpha 函数是 C 和 C++ 标准库中的一个字符处理函数,主要用于判断一个字符是否为字母(包括大写字母和小写字母)。

    C 中的 isalpha 函数

    #include <ctype.h>
    int isalpha(int c);

    C++ 中的 isalpha 函数

    #include <cctype>
    int isalpha(int c);

      参数 c 是一个 int 类型的值,不过在实际使用时通常传入一个 char 类型的值,函数会将其自动转换为 int 类型。isalpha 函数是基于 ASCII 字符集来判断字母的,如果 c 是字母,函数返回一个非零值;如果 c 不是字母,则返回 0。

      getline() 函数

      getline 函数在 C++ 中是一个常用的输入函数,主要用于从输入流中读取一行字符并存储到字符串对象中。

      原型

      #include <iostream>
      #include <string>
      
      std::istream& getline(std::istream& is, std::string& str, char delim);//delim(可选):指定行分隔符,默认为换行符 '\n'
      std::istream& getline(std::istream& is, std::string& str);

      举例

      //std::getline(std::cin, line) 从标准输入读取一行内容,直到遇到换行符 '\n' 为止,并将读取的内容存储到 line 字符串中
      #include <iostream>
      #include <string>
      
      int main() {
          std::string line;
          std::cout << "请输入一行文本:";
          std::getline(std::cin, line);
          std::cout << "你输入的文本是:" << line << std::endl;
          return 0;
      }
      //指定了分隔符为逗号 ',',程序会从标准输入读取内容,直到遇到逗号为止,并将读取的内容存储到 input 字符串中
      #include <iostream>
      #include <string>
      
      int main() {
          std::string input;
          std::cout << "请输入以逗号分隔的内容:";
          std::getline(std::cin, input, ',');
          std::cout << "读取到的内容是:" << input << std::endl;
          return 0;
      }
      评论
      添加红包

      请填写红包祝福语或标题

      红包个数最小为10个

      红包金额最低5元

      当前余额3.43前往充值 >
      需支付:10.00
      成就一亿技术人!
      领取后你会自动成为博主和红包主的粉丝 规则
      hope_wisdom
      发出的红包

      打赏作者

      rigidwill666

      你的鼓励将是我创作的最大动力!

      ¥1 ¥2 ¥4 ¥6 ¥10 ¥20
      扫码支付:¥1
      获取中
      扫码支付

      您的余额不足,请更换扫码支付或充值

      打赏作者

      实付
      使用余额支付
      点击重新获取
      扫码支付
      钱包余额 0

      抵扣说明:

      1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
      2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

      余额充值