Every day a Leetcode
题目来源:3039. 进行操作使字符串为空
解法1:哈希 + 排序
操作的定义:每次操作依次遍历 ‘a’ 到 ‘z’,如果当前字符出现在 s 中,那么删除出现位置最早的该字符(如果存在的话)。
最后一次操作之前的字符串 s 是出现次数最多的字符(可能不止一个)按最后出现位置下标从小到大排列的结果。
我们用一个哈希表 cnt 记录各字符的出现次数,一个数组 lastIndex 记录每个字符最后一次出现的位置下标。
设 max_cnt = *max_element(cnt.begin(), cnt.end()),用一个数组 idx 记录 cnt 中元素值等于 max_cnt 的对应位置下标,则 idx 里存储的就是答案字符串的字符在原字符串的最后一次出现的位置下标。
答案 ans 的长度就是数组 idx 的元素个数。
对 idx 进行增序排序,遍历数组 idx,则 ans[i] 即为 s[idx[i]]。
最后返回 ans。
代码:
/*
* @lc app=leetcode.cn id=3039 lang=cpp
*
* [3039] 进行操作使字符串为空
*/
// @lc code=start
// 哈希 + 排序
class Solution
{
public:
string lastNonEmptyString(string s)
{
if (s.empty())
return "";
vector<int> cnt(26, 0); // 字符的出现次数
vector<int> lastIndex(26, -1); // 字符的最后下标
for (int i = 0; i < s.length(); i++)
{
char c = s[i];
cnt[c - 'a']++;
lastIndex[c - 'a'] = i;
}
int max_cnt = *max_element(cnt.begin(), cnt.end());
vector<int> idx;
for (int i = 0; i < 26; i++)
{
if (cnt[i] == max_cnt)
idx.push_back(lastIndex[i]);
}
sort(idx.begin(), idx.end());
string ans(idx.size(), 0);
for (int i = 0; i < idx.size(); i++)
ans[i] = s[idx[i]];
return ans;
}
};
// @lc code=end
结果:
复杂度分析:
时间复杂度:O(n+∣Σ∣log∣Σ∣),其中 其中 n 为字符串s 的长度,∣Σ∣ 为字符集合的大小,本题中字符均为小写字母,所以 ∣Σ∣=26。
空间复杂度:O(∣Σ∣),其中 ∣Σ∣ 为字符集合的大小,本题中字符均为小写字母,所以 ∣Σ∣=26。