155. 最小栈 - 力扣(LeetCode)
class MinStack {
public:
stack<int> st;
stack<int> minst;
MinStack() {
minst.push(INT_MAX);
}
void push(int val) {
st.push(val);
minst.push(min(minst.top(), val));
}
void pop() {
st.pop();
minst.pop();
}
int top() {
return st.top();
}
int getMin() {
return minst.top();
}
};
/**
* Your MinStack object will be instantiated and called as such:
* MinStack* obj = new MinStack();
* obj->push(val);
* obj->pop();
* int param_3 = obj->top();
* int param_4 = obj->getMin();
*/
146. LRU 缓存机制 - 力扣(LeetCode)
struct DlinkNode{
int key, val;
DlinkNode* pre;
DlinkNode* next;
DlinkNode(): key(0), val(0), pre(nullptr), next(nullptr){}//赋初值
DlinkNode(int key, int val): key(key), val(val), pre(nullptr), next(nullptr){}
};
class LRUCache {
private:
unordered_map<int, DlinkNode*> mp;//关键词到节点的映射,方便快速查找
DlinkNode* head;
DlinkNode* tail;
int size;
int capacity;
public:
LRUCache(int _capacity): capacity(_capacity), size(0) {
head = new DlinkNode();//伪头部节点和伪尾部节点
tail = new DlinkNode();//方便可以尾节点删除和头节点插入
head->next = tail;
tail->pre = head;
}
int get(int key) {
//找到这个节点,如果存在,移动到头部
if(!mp.count(key))
return -1;
DlinkNode* node = mp[key];
movetohead(node);
return node->val;
}
void put(int key, int value) {
if(!mp.count(key))
{
DlinkNode* node = new DlinkNode(key, value);
mp[key] = node;
addtohead(node);
++ size;
if(size > capacity)
{
DlinkNode* re = removeTail();//移动
mp.erase(re->key);//擦除
delete re;//防止内存泄露
-- size;
}
}
else
{
DlinkNode* node = mp[key];
node->val = value;
movetohead(node);
}
}
void removenode(DlinkNode* node)
{
node->pre->next = node->next;
node->next->pre = node->pre;
}
void addtohead(DlinkNode* node)
{
node->pre = head;
node->next = head->next;
head->next->pre = node;
head->next = node;
}
void movetohead(DlinkNode* node)
{
removenode(node);
addtohead(node);
}
DlinkNode* removeTail()
{
DlinkNode* node = tail->pre;
removenode(node);
return node;
}
};
使用自带的list双向列表
注意mp
中存放的是迭代器,需要用->
指向,li
中存放的是PII
,用.
指向
splice是list的一个函数,它可以将一个list中的某个迭代器剪切到自己的某个迭代器部分。
C++ List(列表) - 基础教程在线
class LRUCache {
typedef pair<int, int> PII;
int size;
list<PII> li;
unordered_map<int, list<PII>::iterator> mp;
public:
LRUCache(int capacity): size(capacity) {}
int get(int key) {
if(!mp.count(key)) return -1;
li.splice(li.begin(), li, mp[key]);
return mp[key]->second;
}
void put(int key, int value) {
if(get(key) != -1) mp[key]->second = value;
else
{
if(li.size() == size)
{
int delkey = li.back().first;
li.pop_back();
mp.erase(delkey);
}
li.push_front({key, value});
mp[key] = li.begin();
}
}
};
341. 扁平化嵌套列表迭代器 - 力扣(LeetCode)
class NestedIterator {
vector<int> data;
int index=0;
public:
NestedIterator(vector<NestedInteger> &nestedList) {
dfs(nestedList);
}
void dfs(vector<NestedInteger> &nestedList)
{
for(int i=0;i<nestedList.size();i++)
{
if(nestedList[i].isInteger())
data.push_back(nestedList[i].getInteger());
else
dfs(nestedList[i].getList());
}
}
int next() {
return data[index++];
}
bool hasNext() {
if(index>=data.size())return false;
return true;
}
};
380. O(1) 时间插入、删除和获取随机元素 - 力扣(LeetCode)
很容易想到使用hashmap来找到这个数是否存在,但是如何O(1)随机返回集合中的一项呢,这要求哈希表的序号是紧凑的,这样我们可以用一个数组存储所有数据,他的序号是紧凑的,插入可以直接插入到数组的最后,为了O(1)进行删除,我们可以先于最后一个数交换,然后pop。
class RandomizedSet {
public:
vector<int> nums;
unordered_map<int, int> mp;
RandomizedSet() {
}
bool insert(int val) {
if(mp.count(val)) return false;
mp[val] = nums.size();//放到后边
nums.push_back(val);
return true;
}
bool remove(int val) {
if(!mp.count(val)) return false;
int index = mp[val];
mp[nums.back()] = index;
swap(nums[index], nums.back());
nums.pop_back();
mp.erase(val);
return true;
}
int getRandom() {
return nums[rand() % nums.size()];
}
};
460. LFU 缓存 - 力扣(LeetCode)
struct Node{
int cnt, time, key, value;
//time 是最近一次使用时间
Node(int cnt, int time, int key, int value): cnt(cnt), time(time), key(key), value(value){}
bool operator <(const Node&rhs) const {
if(cnt == rhs.cnt) return time < rhs.time;
return cnt < rhs.cnt;
}
};
class LFUCache {
public:
int capacity, time;
unordered_map<int, Node> key_table;
set<Node> S;
LFUCache(int _capacity) {
capacity = _capacity;
time = 0;
key_table.clear();
S.clear();
}
int get(int key) {
if(capacity == 0) return -1;
auto it = key_table.find(key);
if(it == key_table.end()) return -1;
Node cache = it->second;
S.erase(cache);
cache.cnt += 1;
cache.time = time ++;
S.insert(cache);
it->second = cache;
return cache.value;
}
void put(int key, int value) {
if(capacity == 0) return;
auto it = key_table.find(key);
if(it == key_table.end())
{
if(key_table.size() == capacity)
{
key_table.erase(S.begin() -> key);
S.erase(S.begin());
}
Node cache = Node(1, time ++, key, value);
key_table.insert({key, cache});
S.insert(cache);
}
else
{
Node cache = it->second;
S.erase(cache);
cache.cnt +=1;
cache.time = time ++;
cache.value = value;
S.insert(cache);
it->second = cache;
}
}
};
struct Node{
int key, val, freq;
Node(int _key, int _val, int _freq): key(_key), val(_val), freq(_freq){}
};
class LFUCache {
private:
int minfreq, capacity;
unordered_map<int, list<Node>::iterator> key_table;
unordered_map<int, list<Node>> freq_table;
public:
LFUCache(int _capacity) {
minfreq = 0;
capacity = _capacity;
key_table.clear();
freq_table.clear();
}
int get(int key) {
if(capacity == 0) return -1;
auto it = key_table.find(key);
if(it == key_table.end()) return -1;
auto node = it->second;
int val = node->val, freq = node->freq;
freq_table[freq].erase(node);
if(freq_table[freq].size() == 0)
{
freq_table.erase(freq);
if(minfreq == freq) minfreq ++;
}
freq_table[freq + 1].push_front(Node(key, val, freq + 1));
key_table[key] = freq_table[freq + 1].begin();
return val;
}
void put(int key, int value) {
if(capacity == 0) return;
auto it = key_table.find(key);
if(it == key_table.end())
{
if(key_table.size() == capacity)
{
auto it2 = freq_table[minfreq].back();
key_table.erase(it2.key);
freq_table[minfreq].pop_back();
if(freq_table[minfreq].size() == 0)
{
freq_table.erase(minfreq);
}
}
freq_table[1].push_front(Node(key, value, 1));
key_table[key] = freq_table[1].begin();
minfreq = 1;
}
else
{
auto node = it->second;
int freq = node->freq;
freq_table[freq].erase(node);
if(freq_table[freq].size() == 0)
{
freq_table.erase(freq);
if(minfreq == freq) minfreq += 1;
}
freq_table[freq + 1].push_front(Node(key, value, freq + 1));
key_table[key] = freq_table[freq + 1].begin();
}
}
};
895. 最大频率栈 - 力扣(LeetCode)
class FreqStack {
public:
unordered_map<int, int> vf;//记录每个val对应的频率
unordered_map<int, stack<int>> fv;//每个频率对应的val
int maxfre;
FreqStack() {
maxfre = 0;
}
void push(int val) {
++ vf[val];
int freq = vf[val];
maxfre = max(maxfre, freq);
fv[freq].push(val);
}
int pop() {
stack<int>& s = fv[maxfre];
int res = s.top();
s.pop();
-- vf[res];
if(s.size() == 0)
-- maxfre;
return res;
}
};
232. 用栈实现队列 - 力扣(LeetCode)
class MyQueue {
public:
stack<int> st1, st2;
MyQueue() {
}
void push(int x) {
while(st1.size())
{
st2.push(st1.top());
st1.pop();
}
st2.push(x);
while(st2.size())
{
st1.push(st2.top());
st2.pop();
}
}
int pop() {
int top = st1.top();
st1.pop();
return top;
}
int peek() {
return st1.top();
}
bool empty() {
return st1.empty();
}
};
284. 窥探迭代器 题解 - 力扣(LeetCode)
注意,迭代器原有hasNext()
和next()
函数
class PeekingIterator : public Iterator {
public:
int nextValue;
bool exist;
PeekingIterator(const vector<int>& nums) : Iterator(nums) {
exist = Iterator::hasNext();
if (exist)
nextValue = Iterator::next();
}
int peek() {
return nextValue;
}
int next() {
int tmpValue = nextValue;
exist = Iterator::hasNext();
if (exist)
nextValue = Iterator::next();
return tmpValue;
}
bool hasNext() const {
return exist;
}
};
一些stl函数使用方法
multiset/set
begin和end操作产生指向容器内第一个元素和最后一个元素的下一个位置的迭代器,如下所示。这两个迭代器通常用于标记包含容器中所有元素的迭代范围。
c.begin() 返回一个迭代器,它指向容器c的第一个元素
c.end() 返回一个迭代器,它指向容器c的最后一个元素的下一个位置
c.rbegin() 返回一个逆序迭代器,它指向容器c的最后一个元素
c.rend() 返回一个逆序迭代器,它指向容器c的第一个元素前面的位置
c.find()返回一个迭代器,指向value值的元素
c.erase()可以删除某个值得元素,也可以删除迭代器指向的元素
map
c.begin() 返回一个迭代器,它指向容器c的第一个元素
c.end() 返回一个迭代器,它指向容器c的最后一个元素的下一个位置
c.rbegin() 返回一个逆序迭代器,它指向容器c的最后一个元素