链表
虚拟头节点
当你需要创造一条新链表的时候,可以使用虚拟头结点简化边界情况的处理。
ListNode* dummy = new ListNode(-1)
总的来说,如果我们需要把原链表的节点接到新链表上,而不是 new 新节点来组成新链表的话,那么断开节点和原链表之间的链接可能是必要的。那其实我们可以养成一个好习惯,但凡遇到这种情况,就把原链表的节点断开,这样就不会出错了。
数组
前缀和
NumArray(vector<int>& nums) {
vector<int> preSum;
// preSum[0] = 0,便于计算累加和
preSum.resize(nums.size() + 1);
// 计算 nums 的累加和
for (int i = 1; i < preSum.size(); i++) {
preSum[i] = preSum[i - 1] + nums[i - 1];
}
}
如果我们想求区间nums[i..j]的累加和,只要计算preSum[j+1] - preSum[i]
即可。
差分数组
// 差分数组工具类
class Difference {
// 差分数组
private:
int* diff;
/* 输入一个初始数组,区间操作将在这个数组上进行 */
public:
Difference(int* nums, int length) {
assert(length > 0);
diff = new int[length]();
diff[0] = nums[0];
for (int i = 1; i < length; i++) {
diff[i] = nums[i] - nums[i - 1];
}
}
/* 给闭区间 [i, j] 增加 val(可以是负数)*/
void increment(int i, int j, int val) {
diff[i] += val;
if (j + 1 < sizeof(diff) / sizeof(diff[0])) {
diff[j + 1] -= val;
}
}
/* 返回结果数组 */
int* result() {
int* res = new int[sizeof(diff) / sizeof(diff[0])]();
res[0] = diff[0];
for (int i = 1; i < sizeof(diff) / sizeof(diff[0]); i++) {
res[i] = res[i - 1] + diff[i];
}
return res;
}
};
双向链表+哈希表实现LFU
struct Node {
int key;
int val;
int freq;
Node* prev;
Node* next;
Node () : key(-1), val(-1), freq(0), prev(nullptr), next(nullptr) {}
Node (int _k, int _v) : key(_k), val(_v), freq(1), prev(nullptr), next(nullptr) {}
};
struct FreqList {
int freq;
Node* vhead;
Node* vtail;
FreqList (int _f) : freq(_f), vhead(new Node()), vtail(new Node()) {
vhead->next = vtail;
vtail->prev = vhead;
}
};
class LFUCache {
private:
unordered_map<int, Node*> occ;
unordered_map<int, FreqList*> freq_map;
int sz;
int min_freq;
public:
LFUCache (int capacity) : sz(capacity) {}
bool empty(FreqList* l) {
return l->vhead->next == l->vtail ? true : false;
}
void deleteNode (Node* t) {
t->prev->next = t->next;
t->next->prev = t->prev;
}
void addHead (Node* t) {
int freq = t->freq;
if (freq_map.find(freq) == freq_map.end()) {
freq_map[freq] = new FreqList(freq);
}
FreqList* l = freq_map[freq];
t->next = l->vhead->next;
l->vhead->next->prev = t;
t->prev = l->vhead;
l->vhead->next = t;
}
void popTail () {
Node* t = freq_map[min_freq]->vtail->prev;
deleteNode(t);
occ.erase(t->key);
}
int get (int key) {
int res = -1;
if (occ.find(key) != occ.end()) {
Node* t = occ[key];
res = t->val;
deleteNode(t);
t->freq++;
if (empty(freq_map[min_freq])) min_freq++;
addHead(t);
}
return res;
}
void put (int key, int value) {
if (sz == 0) return;
if (get(key) != -1) {
occ[key]->val = value;
}
else {
if (occ.size() == sz) {
popTail();
}
Node* t = new Node(key, value);
occ[key] = t;
min_freq = 1;//新插入的 频率一定最少, 为1
addHead(t);
}
}
};