青训营X 豆包MarsCode AI 刷题|字符串字符类型排序问题、小C点菜问题

45 阅读4分钟

 一、字符串字符类型排序问题

题目

给定一个字符串,其中仅包含,大小写字母,数字和问号。要求对该字符串内部字符排序,满足以下要求:

  1. 问号的占用的位置不变
  2. 数字占用的位置不变,数字之间由大到小排序
  3. 字母占用的位置不变,字母之间按字典序排序

具体请配合样例理解

样例

输入:

12A?zc

输出:

21A?cz

输入:

1Ad?z?t24

输出:

4Ad?t?z21

输入:

???123??zxy?

输出:

???321??xyz?

解题思路: 

问题理解

我们需要对给定的字符串进行排序,但有以下特殊要求:

  1. 问号的位置保持不变
  2. 数字的位置保持不变,但数字之间按从大到小排序
  3. 字母的位置保持不变,但字母之间按字典序排序

数据结构选择

  1. 问号的位置:我们可以通过遍历字符串,记录问号的位置。
  2. 数字和字母的排序:我们可以分别提取出数字和字母,进行排序,然后再放回原位置。

算法步骤

  1. 记录问号的位置:遍历字符串,记录问号的位置。
  2. 提取数字和字母:遍历字符串,提取出所有的数字和字母。
  3. 排序:对提取出的数字按从大到小排序,对提取出的字母按字典序排序。
  4. 重组字符串:根据记录的问号位置和排序后的数字、字母,重组字符串。

最终代码:

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;

string solution(string inp) {
    // 记录问号的位置
    vector<int> questionMarks;
    for (int i = 0; i < inp.size(); ++i) {
        if (inp[i] == '?') {
            questionMarks.push_back(i);
        }
    }

    // 提取数字和字母
    vector<char> digits;
    vector<char> letters;
    for (char c : inp) {
        if (isdigit(c)) {
            digits.push_back(c);
        } else if (isalpha(c)) {
            letters.push_back(c);
        }
    }

    // 排序
    sort(digits.begin(), digits.end(), greater<char>());
    sort(letters.begin(), letters.end());

    // 重组字符串
    string result = inp;
    int digitIndex = 0;
    int letterIndex = 0;
    for (int i = 0; i < result.size(); ++i) {
        if (result[i] == '?') continue;
        if (isdigit(result[i])) {
            result[i] = digits[digitIndex++];
        } else if (isalpha(result[i])) {
            result[i] = letters[letterIndex++];
        }
    }

    return result;
}

int main() {
    // Add your test cases here

    cout << (solution("12A?zc") == "21A?cz") << endl;
    cout << (solution("1Ad?z?t24") == "4Ad?t?z21") << endl;
    cout << (solution("???123??zxy?") == "???321??xyz?") << endl;

    return 0;
}

运行结果:

​编辑

二、小C点菜问题

问题描述

小C来到了一家餐馆,准备点一些菜。

已知该餐馆有 nn 道菜,第 ii 道菜的售价为 wiwi​。

小C准备点一些价格相同的菜,但小C不会点单价超过 mm 的菜。

小C想知道,自己最多可以点多少道菜?


测试样例

样例1:

输入:m = 6, w = [2, 3, 3, 6, 6, 6, 9, 9, 23]
输出:3

样例2:

输入:m = 4, w = [1, 2, 4, 4, 4]

解题思路: 

问题理解

小C想要点一些价格相同的菜,并且这些菜的价格不能超过给定的上限 m。我们需要找出在满足这个条件下,小C最多可以点多少道菜。

数据结构选择

我们可以使用一个数组来存储每道菜的价格。为了快速统计每种价格的菜的数量,我们可以使用一个哈希表(在C++中可以使用 std::unordered_map)来记录每种价格的菜的数量。

算法步骤

  1. 遍历价格数组:统计每种价格的菜的数量,并将结果存储在哈希表中。
  2. 筛选价格:遍历哈希表,只考虑价格不超过 m 的菜。
  3. 找出最大数量:在筛选后的价格中,找出数量最多的那个,即为小C最多可以点的菜的数量。

最终代码:

#include <bits/stdc++.h>

using namespace std;

long solution(int m, const std::vector<int> w) {
    // 1. 统计每种价格的菜的数量
    std::unordered_map<int, int> priceCount;
    for (int price : w) {
        if (price <= m) {
            priceCount[price]++;
        }
    }
    
    // 2. 找出数量最多的菜
    int maxCount = 0;
    for (const auto& pair : priceCount) {
        if (pair.second > maxCount) {
            maxCount = pair.second;
        }
    }
    
    return maxCount;
}
int main() {
    std::cout << (solution(6, {2, 3, 3, 6, 6, 6, 9, 9, 23}) == 3) << std::endl;
    std::cout << (solution(4, {1, 2, 4, 4, 4}) == 3) << std::endl;
    std::cout << (solution(5, {5, 5, 5, 5, 6, 7, 8}) == 4) << std::endl;
    return 0;
}

运行结果: