整体思路是:
使用双向链表数据结构来存储 LRU,结构如下:
typedef struct LRU_LIST_NODE { int key, value; struct LRU_LIST_NODE *prev, *next; } LRU_LIST_NODE_t;
typedef struct { LRU_LIST_NODE_t *head; /* point to the oldest node */ LRU_LIST_NODE_t *tail; /* point to the latest node */ int node_cnt; /* node count */ int max_node_num; /* k */ } LRU_LIST;
head 的 next 指针指向 oldest 节点,即每次淘汰的时候,淘汰 head->next;
tail 的 prev 指针指向 latest 节点,即每次更新操作后,将更新的节点放到 tail->prev分别定义如下的 API:
void LRU_INIT(LRU_LIST *list, int k); /* 初始化 cache list */ LRU_LIST_NODE_t* LRU_SEARCH(LRU_LIST *list, int key); /* 查找 key 对应的 ndoe */ void LRU_UPDATE(LRU_LIST *list, LRU_LIST_NODE_t *node); /* 更新 node 到最新 */ int LRU_SET(LRU_LIST* list, int key, int value); /* 插入 key, value */ int LRU_GET(LRU_LIST* list, int key); /* 获取 key 对应的 value */
下面是项目代码, 有些变量在牛客网下面如果编译不通过,修改下即可
typedef struct LRU_LIST_NODE { int key, value; struct LRU_LIST_NODE *prev, *next; } LRU_LIST_NODE_t; typedef struct { LRU_LIST_NODE_t *head; /* point the oldest node */ LRU_LIST_NODE_t *tail; /* point the latest node */ int node_cnt; /* node count */ int max_node_num; /* k */ } LRU_LIST; LRU_LIST_NODE_t* LRU_SEARCH(LRU_LIST *list, int key) { LRU_LIST_NODE_t *h = list->head->next; while (h != list->tail) { if (h->key == key) { return h; } h = h->next; } return NULL; } /* adjust the node to the tail */ void LRU_UPDATE(LRU_LIST *list, LRU_LIST_NODE_t *node) { if (list->node_cnt == 1) { return; } /* remove this node first */ LRU_LIST_NODE_t *p = node->prev; p->next = node->next; node->next->prev = p; /* then, insert to the tail */ LRU_LIST_NODE_t *ori_latest_node = list->tail->prev; ori_latest_node->next = node; node->prev = ori_latest_node; node->next = list->tail; list->tail->prev = node; } int LRU_SET(LRU_LIST* list, int key, int value) { LRU_LIST_NODE_t *node = LRU_SEARCH(list, key); if (node != NULL) { node->value = value; /* update */ LRU_UPDATE(list, node); return 0; } /* insert */ if (list->node_cnt == list->max_node_num) { /* delete the oldest if list is full */ LRU_LIST_NODE_t *oldest_node = list->head->next; list->head->next = oldest_node->next; oldest_node->next->prev = list->head; free(oldest_node); } LRU_LIST_NODE_t *new_node = (LRU_LIST_NODE_t *)malloc(sizeof(LRU_LIST_NODE_t)); if (new_node == NULL) { return -1; } new_node->key = key; new_node->value = value; /* insert to the latest */ LRU_LIST_NODE_t *ori_latest = list->tail->prev; ori_latest->next = new_node; list->tail->prev = new_node; new_node->next = list->tail; new_node->prev = ori_latest; /* 坑 1 */ if (list->node_cnt != list->max_node_num) { list->node_cnt++; } return 0; } int LRU_GET(LRU_LIST* list, int key) { LRU_LIST_NODE_t *node = LRU_SEARCH(list, key); if (node == NULL) { return -1; } LRU_UPDATE(list, node); return node->value; } void LRU_INIT(LRU_LIST *list, int k) { list->max_node_num = k; list->head = (LRU_LIST_NODE_t *)malloc(sizeof(LRU_LIST_NODE_t)); list->tail = (LRU_LIST_NODE_t *) malloc (sizeof(LRU_LIST_NODE_t)); list->head ->next = list->tail; list->head->prev = NULL; list->tail->next = NULL; list->tail->prev = list->head; list->node_cnt = 0; } /* parse operator */ int judgeOps(int *operator, int operatorCplen) { if (operator[0] == 1 && operatorCplen == 3) { return 0; } if (operator[0] == 2 && operatorCplen == 2) { return 0; } return -1; } LRU_LIST list; int LRU_RES[102400]; int* LRU(int** operators, int operatorsRowLen, int* operatorsColLen, int k, int* returnSize) { // write code here if (list.max_node_num != k) { LRU_INIT(&list, k); } *returnSize = 0; for (int i = 0; i < operatorsRowLen; i++) { int *ope = operators[i]; int opeLen = operatorsColLen[i]; if (judgeOps(ope, opeLen) != 0) { return LRU_RES; } if (ope[0] == 1) { LRU_SET(&list, ope[1], ope[2]); } else { LRU_RES[*returnSize] = LRU_GET(&list, ope[1]); (*returnSize)++; } } return LRU_RES; }