classMyCircularDeque { private: size_t cap; size_t size; int* array; int* first; int* last; int* circlePointer(int* p) { if (p < array) return array + cap - 1; if (p > array + cap - 1) return array; return p; } int* nextFirst() { returncirclePointer(first - 1); } int* prevFirst() { returncirclePointer(first + 1); } int* nextLast() { returncirclePointer(last + 1); } int* prevLast() { returncirclePointer(last - 1); } public: /** Initialize your data structure here. Set the size of the deque to be k. */ MyCircularDeque(int k): cap(k), size(0), array(newint[k]), first(array), last(array + 1) {} ~MyCircularDeque() { //We are not responsible for deleteing all the objects in the array. Before calling the dtor of this class, clients should do it instead. delete[] array; } /** Adds an item at the front of Deque. Return true if the operation is successful. */ boolinsertLast(int value){ if (isFull()) returnfalse; *first = value; ++size; first = nextFirst(); returntrue; } /** Adds an item at the rear of Deque. Return true if the operation is successful. */ boolinsertFront(int value){ if (isFull()) returnfalse; *last = value; ++size; last = nextLast(); returntrue; } /** Deletes an item from the front of Deque. Return true if the operation is successful. */ booldeleteLast(){ if (isEmpty()) returnfalse; first = prevFirst(); --size; returntrue; } /** Deletes an item from the rear of Deque. Return true if the operation is successful. */ booldeleteFront(){ if (isEmpty()) returnfalse; last = prevLast(); --size; returntrue; } /** Get the front item from the deque. */ intgetRear(){ if(isEmpty()) return-1; return *prevFirst(); } /** Get the last item from the deque. */ intgetFront(){ if(isEmpty()) return-1; return *prevLast(); } /** Checks whether the circular deque is empty or not. */ boolisEmpty(){ return size == 0; } /** Checks whether the circular deque is full or not. */ boolisFull(){ return size == cap; } };
classMyQueue { private: stack<int> s1; stack<int> s2; public: /** Initialize your data structure here. */ MyQueue(): s1{}, s2{} {} /** Push element x to the back of queue. */ voidpush(int x){ s1.push(x); } /** Removes the element from in front of queue and returns that element. */ intpop(){ int res = peek(); s2.pop(); return res; } /** Get the front element. */ intpeek(){ if(s2.empty()) { while(!s1.empty()) { s2.push(s1.top()); s1.pop(); } }
return s2.top(); } /** Returns whether the queue is empty. */ boolempty(){ return s1.empty() && s2.empty(); } };
/** Push element x onto stack. */ voidpush(int x){ q1->push(x); } /** Removes the element on top of the stack and returns that element. */ intpop(){ while(q1->size() > 1) { q2->push(q1->front()); q1->pop(); } auto val = q1->front(); q1->pop(); swap(q1, q2); return val; } /** Get the top element. */ inttop(){ return q1->back(); } /** Returns whether the stack is empty. */ boolempty(){ return q1->empty(); } };
最小栈
LC155, Min Stack Design a stack that supports push, pop, top, and retrieving the minimum element in constant time. 思路:
intpop(){ auto range = maxSet.equal_range(l.begin()); auto it = range.first; for(;*it != l.begin();++it); maxSet.erase(it); int top = l.front(); l.pop_front(); return top; }
inttop(){ return l.front(); }
intpeekMax(){ return **(--maxSet.end()); }
intpopMax(){ auto maxIt = (--maxSet.end()); auto max = **maxIt; l.erase(*maxIt); maxSet.erase(maxIt); return max; } };
voidpush(int x){ // we update the freq map // if we cannot find the key, initialize it if(freq.find(x) == freq.end()) { freq[x] = 1; } else// the key could be found. { ++freq[x]; } assert(freq[x] != 0); // check if the freq stack of this freq is initilized if(freqMap.find(freq[x]) == freqMap.end()) freqMap[freq[x]] = new stack<int>{{x}}; else freqMap[freq[x]]->push(x); }
intpop(){ auto maxFreqStack = freqMap[freqMap.size()]; int res = maxFreqStack->top(); maxFreqStack->pop(); --freq[res]; if(maxFreqStack->empty()){ freqMap.erase(freqMap.find(freqMap.size())); delete maxFreqStack; } return res; } };
auto toDigit = [](char c)->int{return c - ASCII_0;};
for (auto i = s.begin(); i != s.end(); ++i) { if(isdigit(*i)) { string num{}; while(isdigit(*i)) { num.push_back(*i); ++i; } stack.emplace_back(atoi(num.c_str()), string{}); continue; } elseif(*i == ASCII_LEFT_BRACKET) { // skip the '[', it is useless. continue; } elseif(*i == ASCII_RIGHT_BRACKET) { // append N copies of stack.top().second() // to the numStringPair before stack.top()
auto topIt = --stack.end(); auto nextTopIt = topIt - 1;
stack.pop_back(); } else// i is a letter { stack.back().second.push_back(*i); } } // now there should be only one string in the stack assert(stack.size() == 1); return stack.front().second; } };
单调栈
考虑一个递增栈,设栈顶元素为t,将要推入栈中的元素为n
- 1: 如果 n > t, 将 n 推入栈中。此时 t 是 n 左侧第一个比他小的元素。
- 2: 否则, 将栈顶t弹出,如果栈非空,设新的栈顶为t2
- t2 是 t **左侧第一个比他小的元素**
- n 是 t **右侧第一个比他小的元素**
- 回到1
考虑一个递减栈,设栈顶元素为t,将要推入栈中的元素为n
- 如果 n < t,将 n 推入栈中。此时 t 是 n 左侧第一个比他大的元素
- 否则,将栈顶t弹出,如果栈非空,设新的栈顶为t2
- t2 是 t **左侧第一个比他大的元素**
- n 是 t **右侧第一个比他大的元素**
栈里一般存放元素的指针或者元素的index。需要弹出栈中元素,一般也是用来计算的结果的时候。
单调递增栈,栈内元素的性质图解: 单调递增栈栈内两个相邻的元素$ay > a_x, y > x$,在其原来的数组中,$a_y$和$a_x$之间的元素都在$(a_y, +\infty)$的范围内。即他们之间的元素$a{i}, i \in (x, y)$,必然有$a_{i} > a_y$
classSolution { public: inttrap(vector<int>& height){ height.push_back(0); auto monoStack = vector<vector<int>::iterator>{}; int res = 0;
for(auto it = height.begin(); it < height.end(); ++it) { while(!monoStack.empty() && *monoStack.back() < *it) { auto mid = monoStack.back(); monoStack.pop_back(); // if there is no more element on the left, we can trap any water. if(monoStack.empty()) break; auto left = monoStack.back(); // compute how many water it could trap res += (it - left - 1) * (min(*it, *left) - *mid); } monoStack.push_back(it); }
classSolution { public: inttrap(vector<int>& height){ stack<vector<int>::iterator> s{}; int res = 0; for(auto it = height.begin(); it != height.end(); ++it) { while (!s.empty() && *s.top() < *it ) { auto r = it; auto m = s.top(); s.pop(); if (s.empty()) {s.push(it);break;} auto l = s.top(); res += computeTrap(l, m, r); } s.push(it); } return res; } template<typename It> intcomputeTrap(It l, It m, It r) { int width = distance(l,r) - 1; int height = min(*l,*r) - *m; return width * height; } };
classSolution { public: intmaximalRectangle(vector<vector<char>>& matrix){ if (matrix.empty() || matrix.front().empty()) return0; // build the histograms vector<vector<size_t>> histograms(matrix.size(), vector<size_t>(matrix[0].size())); // put the first row into the histogram. for(size_t i = 0; i < matrix[0].size(); ++i) { histograms[0][i] = matrix[0][i] == '1' ? 1 : 0; }
intmaximalRectangleInHistogram(vector<size_t>& histogram) { // put the guard into the back of the histogram. histogram.push_back(0); // monoStack stack<vector<size_t>::iterator> stack{}; size_t rectArea = 0;
for(auto it = histogram.begin(); it != histogram.end(); ++it) { // violation of increasing order. while(!stack.empty() && *it < *stack.top()) { auto topIt = stack.top(); stack.pop();
// the leftBound is the "element" before begin. if(stack.empty()) { rectArea = max(rectArea, distance(histogram.begin(), it) * (*topIt)); } // the leftBound is the top element of the stack. else { rectArea = max(rectArea, (distance(stack.top(), it) - 1) * (*topIt)); }