The tricky thing was keeping copies of list iterators in a tree map and managing both together. I'm not handling invalid input cases (like popping an empty stack) in this code. I am following Google C++ style guide. Any advice and feedback would be appreciated!
// A Max Stack data structure which supports the push/pop LIFO operations
// of a stack and allows removal of the largest number
class MaxStack {
// Doubly linked list serving as a stack
list<int> dll_;
// Tree map mapping user added values to iterator references in the
// doubly linked list
map<int, vector<list<int>::iterator>, std::greater<int>> bst_;
public:
// Push element into the data structures
// - Push to the end of doubly linked list
// - Push the iterator from the doubly linked list to the vector
// corresponding to the key of the input number
void Push(int x) {
dll_.push_back(x);
if (bst_.find(x) == bst_.end()) {
bst_[x] = vector<list<int>::iterator>();
}
bst_[x].push_back(std::prev(dll_.end()));
}
// Pop from the top of the stack and remove the corresponding iterator
// from the map
int Pop() {
int val = *(dll_.rbegin());
auto to_delete = *(bst_[val].rbegin());
dll_.erase(to_delete);
bst_[val].pop_back();
// Remove the key from the map if nothing is left
if (bst_[val].empty()) {
bst_.erase(val);
}
return val;
}
int Top() {
return *(dll_.rbegin());
}
int PeekMax() {
return bst_.begin()->first;
}
// Remove one instance of the largest element in the tree map
// and the corresponding node in the doubly linked list.
// If there are multiple largest elements, remove the most recently
// added one.
int PopMax() {
int val = bst_.begin()->first;
auto to_delete = *(bst_[val].rbegin());
dll_.erase(to_delete);
bst_[val].pop_back();
// Remove the key from the map if nothing is left
if (bst_[val].empty()) {
bst_.erase(val);
}
return val;
}
};
```