描述
题目描述
这个题乍一看很复杂,其实逐步分解就可以
首先Insert这个函数是用于每次新增一个字符的,然后FirstAppearingOnce这个函数是直接输出每次第一个只出现一次的字符是什么的
样例解释
首先给定我们的样例输入
"google"
这个是怎么判断呢?
所以最后的输出就是
"ggg#ll"
题解
解法一:队列
实现思路:
首先我们可以用一个队列模拟我们每次入队的字符,然后同时我们每次记录我们这个字符出现的次数,然后查找的时候就是看我们队头是不是只出现了一次,如果是的话,我们可以直接输出,否则弹出看下一个,然后如果都不是的话就是输出
代码实现:
class Solution
{
queue<char> q;
int cnt[257];
// q保存着我们的一个我们输入的字符
// cnt里面存储的是我们每一个字符出现的位置
public:
void Insert(char ch) {
q.push(ch);
++ cnt[ch + '0'];
// 每次把我们插入的字符入队
// 并且记录出现的次数
}
char FirstAppearingOnce() {
while (q.size()) {
// 如果队列不空
char res = q.front();
// 获取队头元素
if (cnt[res + '0'] == 1) return res;
// 如果队头是只出现了一次的,我们直接返回
q.pop();
// 如果不是的话,直接弹出
}
return '#';
// 最后发现一个都没有,返回#
}
};
时空复杂度分析:
时间复杂度:
理由如下:最坏清空下,我们是要遍历一半我们的这个字符流的长度
空间复杂度:
理由如下:我们开辟了一个记录次数的数组,然后我们的队列极限清空下会存储所有的字符流
解法二:
解题思路
首先我们可以定义一个哈希表,我们用于存储我们每一个字符出现的次数,然后我们还有一个字符串就是我们总共输入的这个字符串,我们每次插入之后可以遍历一次我们的字符串,如果我们是可以从前到后找到当前的字符满足只出现了一次的话,我们就可以把这个输出,如果都没有的话,我们最后返回的就是
代码实现
class Solution
{
unordered_map<char, int> mp;
// 存储每一个字符出现的次数
string s = "";
// 我们的字符串
public:
void Insert(char ch) {
s += ch;
// 插入我们新的字符串
mp[ch] += 1;
// 字符的个数加一
}
char FirstAppearingOnce() {
for (auto &it : s) {
if (mp[it] == 1) return it;
}
// 从头到尾遍历我们的字符串,如果存在一个等于1的那么我们可以直接返回
return '#';
// 都没有的话,我们返回#
}
};
时空复杂度分析
时间复杂度:
理由如下:主要的时间就是花费在我们遍历我们的字符串上
空间复杂度:
理由如下:因为我们要存储所有输入进来的字符,最后构成一个字符串,所以我们最后的空间会是我们字符串的长度,哈希表最多是ASCLL码的范围这个可以忽略