形式化地,给定一个长度为n 的字符串s 和常数 k,你需要求出它的一个非空子序列 t,满足存在恰好k 种字母,使得其在s 中出现过,但没有在 t中出现过。若无解,输出 -1 ,否则输出字典序最小的方 案。 写一个c++代码来解决
时间: 2024-09-29 21:06:44 浏览: 30
这是一个经典的动态规划问题,通常可以用暴力搜索辅助动态规划的方式来解决。这里给出一种可能的C++解决方案:
```cpp
#include <vector>
#include <string>
#include <unordered_map>
std::string findSubsequence(std::string s, int k) {
if (s.empty() || k == 0) return "-1";
std::vector<int> count(26, 0); // 初始化每个字母计数为0
for (char c : s) {
count[c - 'a']++; // 更新字符计数
}
if (count.size() < k) return "-1"; // 如果需要的唯一字符种类超过实际种类,无解
std::string result = ""; // 存储结果
std::unordered_map<char, bool> used; // 标记已使用的字符
for (int i = 0; i < s.length(); ++i) {
char current = s[i];
if (!used[current] && count[current - 'a'] > 0) {
result += current;
used[current] = true;
count[current - 'a']--;
// 检查是否达到k个独特字符
if (result.size() == k) break;
}
}
// 如果结果包含k个独特字符,返回字典序最小的;否则返回-1
sort(result.begin(), result.end());
return result.size() == k ? result : "-1";
}
```
这个代码首先统计原始字符串s中各字符的频率,然后遍历一遍s,对于每个字符,如果还没被使用并且计数大于0,就将其添加到结果并标记为已使用,同时减小计数。当结果长度达到k时,跳出循环。最后对结果进行排序,并检查是否等于k,等于则返回结果,否则返回"-1"。
注意,这个算法的时间复杂度是O(n log n),其中n是字符串s的长度,因为对结果字符串进行了排序。空间复杂度是O(1)(忽略常数影响)。
阅读全文