目录
一、饭馆菜品选择问题
问题描述
测试样例
解题思路:
问题理解
数据结构选择
算法步骤
最终代码:
运行结果:
二、构造回文字符串问题
问题描述
测试样例
解题思路:
解题思路
具体步骤
最终代码:
运行结果:编辑
一、饭馆菜品选择问题
问题描述
小C来到了一家饭馆,这里共有 nn 道菜,第 ii 道菜的价格为 a_i
。其中一些菜中含有蘑菇,s_i
代表第 ii 道菜是否含有蘑菇。如果 s_i = '1'
,那么第 ii 道菜含有蘑菇,否则没有。
小C希望点 kk 道菜,且希望总价格尽可能低。由于她不喜欢蘑菇,她希望所点的菜中最多只有 mm 道菜含有蘑菇。小C想知道在满足条件的情况下能选出的最小总价格是多少。如果无法按照要求选择菜品,则输出-1
。
测试样例
样例1:
输入:
s = "001", a = [10, 20, 30], m = 1, k = 2
输出:30
样例2:
输入:
s = "111", a = [10, 20, 30], m = 1, k = 2
输出:-1
样例3:
输入:
s = "0101", a = [5, 15, 10, 20], m = 2, k = 3
输出:30
解题思路:
问题理解
小C需要从 n
道菜中选择 k
道菜,且希望总价格尽可能低。同时,她希望所点的菜中最多只有 m
道菜含有蘑菇。我们需要找到满足这些条件的最小总价格,如果无法满足条件则返回 -1
。
数据结构选择
- 菜品数组:我们可以将菜品的价格和是否含有蘑菇的信息存储在一个结构体或类中,以便于后续处理。
- 排序:为了找到最小总价格,我们可以先对菜品按价格进行排序。
算法步骤
- 初始化:创建一个结构体或类来存储菜品的价格和是否含有蘑菇的信息。
- 排序:按价格对菜品进行排序。
- 选择菜品:从排序后的菜品中选择
k
道菜,确保最多有m
道菜含有蘑菇。可以使用贪心算法来逐步选择价格最低的菜品,同时记录已选择的含有蘑菇的菜品数量。 - 检查条件:如果在选择过程中发现无法满足条件(即含有蘑菇的菜品数量超过
m
),则返回-1
。 - 计算总价格:如果成功选择
k
道菜,则计算总价格并返回。
最终代码:
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <limits> // 添加头文件以使用 std::numeric_limitsusing namespace std;long solution(const std::string& s, const std::vector<int>& a, int m, int k) {// 将菜品分为含有蘑菇和不含有蘑菇两类std::vector<int> mushroomPrices;std::vector<int> noMushroomPrices;for (int i = 0; i < s.size(); ++i) {if (s[i] == '1') {mushroomPrices.push_back(a[i]);} else {noMushroomPrices.push_back(a[i]);}}// 对两类菜品的价格进行排序std::sort(mushroomPrices.begin(), mushroomPrices.end());std::sort(noMushroomPrices.begin(), noMushroomPrices.end());// 初始化最小总价格为一个较大的值long minTotalPrice = std::numeric_limits<long>::max(); // 使用 std::numeric_limits<long>::max()// 尝试从两类菜品中选择 k 道菜for (int i = 0; i <= std::min(m, (int)mushroomPrices.size()); ++i) {int j = k - i; // 需要选择的不含有蘑菇的菜品数量// 检查是否可以满足条件if (j <= noMushroomPrices.size()) {// 计算当前组合的总价格long currentTotalPrice = 0;// 计算含有蘑菇的菜品价格for (int x = 0; x < i; ++x) {currentTotalPrice += mushroomPrices[x];}// 计算不含有蘑菇的菜品价格for (int y = 0; y < j; ++y) {currentTotalPrice += noMushroomPrices[y];}// 更新最小总价格minTotalPrice = std::min(minTotalPrice, currentTotalPrice);}}// 如果无法满足条件,返回 -1return minTotalPrice == std::numeric_limits<long>::max() ? -1 : minTotalPrice; // 检查是否仍然是最大值
}int main() {std::cout << (solution("001", {10, 20, 30}, 1, 2) == 30) << std::endl;std::cout << (solution("111", {10, 20, 30}, 1, 2) == -1) << std::endl;std::cout << (solution("0101", {5, 15, 10, 20}, 2, 3) == 30) << std::endl;return 0;
}
运行结果:
二、构造回文字符串问题
问题描述
小C手中有一个由小写字母组成的字符串 s
。她希望构造另一个字符串 t
,并且这个字符串需要满足以下几个条件:
t
由小写字母组成,且长度与s
相同。t
是回文字符串,即从左到右与从右到左读取相同。t
的字典序要小于s
,并且在所有符合条件的字符串中字典序尽可能大。
小C想知道是否能构造出这样的字符串 t
,输出这样的t
。如果无法构造满足条件的字符串,则输出 -1
。
测试样例
样例1:
输入:
s = "abc"
输出:'aba'
样例2:
输入:
s = "cba"
输出:'cac'
样例3:
输入:
s = "aaa"
输出:'-1'
解题思路:
要解决这个问题,我们需要构造一个字符串 t
,它满足以下条件:
t
的长度与s
相同。t
是回文字符串。t
的字典序要小于s
,并且在所有符合条件的字符串中字典序尽可能大。
解题思路
-
回文特性:
- 回文字符串的特点是正读和反读都相同。因此,我们可以通过构造前半部分来确定整个回文字符串。
-
字典序比较:
- 为了使
t
的字典序小于s
,我们需要在前半部分找到一个位置,使得该位置的字符小于s
对应位置的字符。 - 为了使
t
的字典序尽可能大,我们需要在找到这个位置后,尽可能使后续的字符最大。
- 为了使
-
构造回文:
- 如果
s
本身就是回文且所有字符都相同(例如"aaa"
),则无法构造出满足条件的t
,直接返回-1
。 - 否则,从前半部分开始,找到第一个可以减小的字符位置,然后构造回文。
- 如果
具体步骤
-
检查是否已经是回文且所有字符相同:
- 如果是,直接返回
-1
。
- 如果是,直接返回
-
从前半部分开始,找到第一个可以减小的字符位置:
- 例如,对于
s = "abc"
,前半部分是"a"
,找到第一个可以减小的字符位置。
- 例如,对于
-
构造回文:
- 在找到的位置减小字符,然后构造回文。
- 例如,对于
s = "abc"
,找到"a"
可以减小为"a"
,构造回文"aba"
。
-
返回结果:
- 如果成功构造出满足条件的回文,返回该回文;否则返回
-1
。
- 如果成功构造出满足条件的回文,返回该回文;否则返回
最终代码:
#include <iostream>
#include <string>
using namespace std;string solution(string s) {int n = s.length();string t = s; // 转换为列表,方便修改// 先构建一个回文字符串for (int i = 0; i < n / 2; ++i) {t[n - i - 1] = t[i]; // 保持回文性}// 如果初始回文字符串已经小于s,直接返回if (t < s) {return t;}// 否则,从中间开始向前调整for (int i = (n - 1) / 2; i >= 0; --i) {if (t[i] > 'a') { // 如果当前字符大于 'a',可以减小t[i] = t[i] - 1;t[n - i - 1] = t[i]; // 保持回文性// 调整后面的位置为尽可能的小字符 'z',确保字典序最小for (int j = i + 1; j < n - i - 1; ++j) {t[j] = 'z';t[n - j - 1] = t[j];}// 生成回文字符串并检查字典序if (t < s) {return t;} else {// 如果调整后仍然不满足条件,继续尝试下一个字符t[i] = s[i];t[n - i - 1] = s[i];}}}return "-1";
}int main() {cout << (solution("abc") == "aba") << endl; // 输出 1 (true)cout << (solution("cba") == "cac") << endl; // 输出 1 (true)cout << (solution("aaa") == "-1") << endl; // 输出 1 (true)return 0;
}
运行结果: