day 11 on stack and queue design
232. Implement Queue using Stacks
经典的两个stack组成queue, 重点是peek的时候需要把back倒腾到front去
class MyQueue {
stack<int> front_;
stack<int> back_;
public:
MyQueue() {}
void push(int x) {
back_.push(x);
}
int pop() {
if (empty()) return -1;
peek();
int ret = front_.top();front_.pop();
return ret;
}
int peek() {
if (front_.empty()) {
while (!back_.empty()) {
int x = back_.top(); back_.pop();
front_.push(x);
}
}
return front_.top();
}
bool empty() {
return front_.empty() && back_.empty();
}
};
225. Implement Stack using Queues
class MyStack {
queue<int> q;
public:
MyStack() {
}
void push(int x) {
int k = q.size();
q.push(x);
while (k--) {
int x = q.front(); q.pop();
q.push(x);
}
}
int pop() {
if (empty()){
return -1;
}
int ret = q.front(); q.pop();
return ret;
}
int top() {
return q.front();
}
bool empty() {
return q.empty();
}
};
341. Flatten Nested List Iterator
可以把整个数据结构都dump到一个list里面 也可以只留一部分,需要的时候unzip再用
class NestedIterator {
deque<NestedInteger> cache;
public:
NestedIterator(vector<NestedInteger> &nestedList) {
for (auto& ni: nestedList) {
cache.push_back(ni);
}
}
int next() {
if (!hasNext()) return -1;
int ans = cache.front().getInteger();
cache.pop_front();
return ans;
}
bool hasNext() {
while (!cache.empty() && !cache.front().isInteger()) {
vector<NestedInteger> nl = cache.front().getList();
cache.pop_front();
for (int i = nl.size() - 1; i >= 0; i--) {
cache.push_front(nl[i]);
}
}
return !cache.empty();
}
};
716. Max Stack
最简单的办法是maxStack 和data stack 同步, 要删除的时候,利用一个tmp stack,倒腾出来,pop掉和peekMax()一样的,在恢复回去。
class MaxStack {
stack<int> data;
stack<int> maxStack;
public:
MaxStack() {
}
void push(int x) {
int maxSofar = maxStack.empty() ? x : maxStack.top();
maxStack.push(max(maxSofar, x));
data.push(x);
}
int pop() {
int ret = data.top(); data.pop();
maxStack.pop();
return ret;
}
int top() {
return data.top();
}
int peekMax() {
return maxStack.top();
}
int popMax() {
stack<int> tmp;
int maxValue = peekMax();
while (top() != maxValue) {
tmp.push(pop());
}
pop();
while (!tmp.empty()) {
push(tmp.top());
tmp.pop();
}
return maxValue;
}
};
更好的办法是用bst在判断最大, 类似LFU BST of iteratr, 指向一个list, and use vector to store the duplicate element why not multimap? the order matter! why remove if empty, iterator validation
class MaxStack {
using IT = list<int>::iterator;
list<int> l;
map<int, vector<IT>> mp;
public:
MaxStack() {}
void push(int x) {
l.push_front(x);
mp[x].push_back(l.begin());
}
int pop() {
int x = l.front(); l.pop_front();
removeKey(x);
return x;
}
int top() {
return *l.begin();
}
int peekMax() {
return mp.rbegin()->first;
}
int popMax() {
int x = peekMax();
auto it = mp[x].back();
l.erase(it);
removeKey(x);
return x;
}
private:
void removeKey(int x) {
mp[x].pop_back();
if (mp[x].empty()) {
mp.erase(x);
}
}
};
353. Design Snake Game
- 需要注意的是,是先动尾巴还是先动头
- unordered_set/map 没有default的hash function
class SnakeGame {
int W, H;
int pos = 0;
vector<vector<int>> food;
set<pair<int,int>> hist;//<<== no hash function
deque<pair<int,int>> q;
public:
SnakeGame(int width, int height, vector<vector<int>>& food) {
this->food = food;
W = width, H = height;
pos = 0;
q.push_back({0, 0});
}
int move(string direction) {
auto [row, col] = q.front();
auto tail = q.back(); q.pop_back();
hist.erase(tail);
if (direction == "U")
row--;
else if (direction == "D")
row++;
else if (direction == "L")
col--;
else if (direction == "R")
col++;
if (!onboard(row, col) || hist.count({row, col})) {
return -1;//wall
}
hist.insert({row, col});
q.push_front({row, col});
if (pos >= food.size()) {
return q.size() - 1;
}
if (row == food[pos][0] && col == food[pos][1]) {
pos++;
q.push_back(tail);
hist.insert(tail);
}
return q.size() - 1;
}
int onboard(int r, int c) {
return (0 <= r && r < H) && (0 <= c && c < W);
}
};
Written on December 18, 2021