维护两个队列 queue
维护一个自增数 int count = 0;
设计入队的函数,注意push的时候,是push({count, animal[0]}),然后count编号自增。
设计出队的函数;
设计出Dog的函数,注意边界判断,是否queDog为空,如果有Dog,则先进先出,即temp = queDog.front().first;是要返回的,然后pop,return{temp, 1};
同理设计Cat的函数,注意是返回return{temp, 0};,因为0代表猫。
class AnimalShelf {
queue<pair<int,int>> queCat; //猫队列
queue<pair<int,int>> queDog; //狗队列
int cout = 0; //设置自增数
public:
AnimalShelf() {
}
void enqueue(vector<int> animal) {
if(animal[1]) queDog.push({cout,animal[0]}); //种类为狗
else queCat.push({cout,animal[0]}); //种类为猫
cout ++; //编号自增
}
vector<int> dequeueAny() {
if(queDog.empty() && queCat.empty()) return {-1, -1}; //猫狗都为空
else if(queCat.empty() && queDog.size()) return dequeueDog(); //有狗无猫
else if(queDog.empty() && queCat.size()) return dequeueCat(); //有猫无狗
else if(queDog.front() < queCat.front()) return dequeueDog(); //有猫有狗,狗编号小
else return dequeueCat(); //有猫有狗,猫编号小
}
vector<int> dequeueDog() {
if(queDog.empty()) return {-1, -1}; //无狗
int temp = queDog.front().first; //有狗,先进先出
queDog.pop();
return {temp, 1};
}
vector<int> dequeueCat() {
if(queCat.empty()) return {-1, -1}; //无猫
int temp = queCat.front().first; //有猫先进先出
queCat.pop();
return {temp, 0};
}
};
c++中PeekingIterator继承父类Iterator,Iterator已经实现方法next和hasNext。使用flag标记迭代器是否还有剩余元素,使用nextElement存储迭代器的下一个元素
class PeekingIterator : public Iterator {
public:
PeekingIterator(const vector<int>& nums) : Iterator(nums) {
flag = Iterator::hasNext();
if (flag) {
nextElement = Iterator::next();
}
}
int peek() {
return nextElement;
}
int next() {
int ret = nextElement;
flag = Iterator::hasNext();
if (flag) {
nextElement = Iterator::next();
}
return ret;
}
bool hasNext() const {
return flag;
}
private:
int nextElement;
bool flag;
};
时间复杂度:每一项操作的时间复杂度都是 O(1)。
空间复杂度:O(1)。
一个嵌套的整数列表nestedList。每个元素要么是一个整数,要么是一个列表;该列表的元素也可能是整数或者是其他列表。实现一个迭代器将其扁平化,使之能够遍历这个列表中的所有整数。
先遍历整个嵌套列表,将所有整数存入一个数组,然后遍历该数组从而实现next和hasNext方法。
难点:next返回的是嵌套列表的下一个整数,cur是迭代器,cur就是取迭代器所指向的位置的元素值,而cur是vals向量列表的begin,所以需要cur++。这是个容易疏忽的点!(下一个)
class NestedIterator {
private:
vector<int> vals;
vector<int>::iterator cur;
void dfs(const vector<NestedInteger> &nestedList) {
for (auto &nest : nestedList) {
if (nest.isInteger()) {
vals.push_back(nest.getInteger());
} else {
dfs(nest.getList());
}
}
}
public:
NestedIterator(vector<NestedInteger> &nestedList) {
dfs(nestedList);
cur = vals.begin();
}
int next() {
return *cur++;
}
bool hasNext() {
return cur != vals.end();
}
};
设计一个管理n个座位预约的系统,座位编号从1到n。
实现SeatManager类。
对于reserve方法,需要弹出并返回available中的最小元素;
对于unreserve方法,需要将seatNumber添加至available中。
使用二叉堆实现的优先队列作为available。对于一个最小堆,可以在O(log n)的时间复杂度内完成单词添加元素和弹出最小值的操作。
class SeatManager {
public:
vector<int> available;
SeatManager(int n) {
for (int i = 1; i <= n; ++i){
available.push_back(i);
}
}
int reserve() {
pop_heap(available.begin(), available.end(), greater<int>());
int tmp = available.back();
available.pop_back();
return tmp;
}
void unreserve(int seatNumber) {
available.push_back(seatNumber);
push_heap(available.begin(), available.end(), greater<int>());
}
};
当成stack题目,利用双栈分别存储,再保存一个当前的链接,对应操作
class BrowserHistory {
private:
stack<string> backHis;
stack<string> forwardHis;
string presentUrl;
public:
BrowserHistory(string homepage) {
presentUrl = homepage;
}
void visit(string url) {
backHis.push(presentUrl);
presentUrl = url;
while(!forwardHis.empty()) forwardHis.pop();
}
string back(int steps) {
while(steps-- > 0 && !backHis.empty()){
forwardHis.push(presentUrl);
presentUrl = backHis.top();
backHis.pop();
}
return presentUrl;
}
string forward(int steps) {
while(steps-- > 0 && !forwardHis.empty()){
backHis.push(presentUrl);
presentUrl = forwardHis.top();
forwardHis.pop();
}
return presentUrl;
}
};
/**
* Your BrowserHistory object will be instantiated and called as such:
* BrowserHistory* obj = new BrowserHistory(homepage);
* obj->visit(url);
* string param_2 = obj->back(steps);
* string param_3 = obj->forward(steps);
*/
使用unordered_map存储id与初始化的时间的映射。
generate操作就更新到map里面,renew操作先判断有没有和是否超时,再进行更新,countUnexpiredTokens操作就遍历一遍哈希表,寻找未超时的id个数。
一个字符串s和一个整数k,找出s中的最长子串,要求该子串中的每一个字符出现次数都不少于k。返回这一子串的长度。
对于字符串 ss,如果存在某个字符 \textit{ch}ch,它的出现次数大于 00 且小于 kk,则任何包含 \textit{ch}ch 的子串都不可能满足要求。也就是说,我们将字符串按照 \textit{ch}ch 切分成若干段,则满足要求的最长子串一定出现在某个被切分的段内,而不能跨越一个或多个段。因此,可以考虑分治的方式求解本题。
分治法:
class Solution {
public:
int dfs(const string& s, int l, int r, int k) {
vector<int> cnt(26, 0);
for (int i = l; i <= r; i++) {
cnt[s[i] - 'a']++;
}
char split = 0;
for (int i = 0; i < 26; i++) {
if (cnt[i] > 0 && cnt[i] < k) {
split = i + 'a';
break;
}
}
if (split == 0) {
return r - l + 1;
}
int i = l;
int ret = 0;
while (i <= r) {
while (i <= r && s[i] == split) {
i++;
}
if (i > r) {
break;
}
int start = i;
while (i <= r && s[i] != split) {
i++;
}
int length = dfs(s, start, i - 1, k);
ret = max(ret, length);
}
return ret;
}
int longestSubstring(string s, int k) {
int n = s.length();
return dfs(s, 0, n - 1, k);
}
};
滑动窗口
class Solution {
public:
int longestSubstring(string s, int k) {
int ret = 0;
int n = s.length();
for (int t = 1; t <= 26; t++) {
int l = 0, r = 0;
vector<int> cnt(26, 0);
int tot = 0;
int less = 0;
while (r < n) {
cnt[s[r] - 'a']++;
if (cnt[s[r] - 'a'] == 1) {
tot++;
less++;
}
if (cnt[s[r] - 'a'] == k) {
less--;
}
while (tot > t) {
cnt[s[l] - 'a']--;
if (cnt[s[l] - 'a'] == k - 1) {
less++;
}
if (cnt[s[l] - 'a'] == 0) {
tot--;
less--;
}
l++;
}
if (less == 0) {
ret = max(ret, r - l + 1);
}
r++;
}
}
return ret;
}
};