文章目录
- LRU缓存(146)
- 完整代码解答:
- 二叉树的中序遍历(94)
- 完整代码解答:
LRU缓存(146)
从题上看存在Key和Value因此我们采用HashMap来进行存储,这里我们采用HashMap+双向链表来实现,我们需要实现里面的get,put方法。
我们需要先创建1个链表节点
//先定义一个节点类
class ListNode{
//它是一个双向链表
int key;
int value;
ListNode front;
ListNode next;
public ListNode(int key,int value){
this.key = key;
this.value = value;
}
}
这里我们先实现put方法,根据题意:
1.首先我们应该判断当前的Map中是否存在一样的Key。
2.如果有了,我们就直接将原来的Value变成新的Value就行了,同时将这个节点放到首位。
3.如果没有,我们还要先判断HashMap的容量(capacity),如果超过了容量就删除最后一个节点,如果没有超过我们就把新的节点放到链表的末尾同时在HashMap添加。
public void put(int key, int value) {
//先看该链表中有无当前的key,没有的话在添加之前要先确定容量
if(!map.containsKey(key)){
if(map.size() == capacity) {
deletLastNode();
}
//先保存第一个节点即head的下一个节点
ListNode temp = head.next;
//先定义要新添加的节点
ListNode newListNode = new ListNode(key,value);
//head的下一个节点即为第一个节点,因为是双向链表因此需要2次连接
head.next = newListNode;
newListNode.front = head;
//将temp连接到新的链表之后
newListNode.next = temp;
temp.front = newListNode;
//再将新的节点加入map
map.put(key,newListNode);
}else{
//如果map中有key的话,我们仅需要更改里面的value
//先拿到对应key的节点
ListNode list1 = map.get(key);
list1.value = value;
//因为我们做了1次修改,我们应该把修改的那个节点放在最前面
putNodeFirst(list1);
}
}
同时这里面涉及到了将节点放到首位的方法: putNodeFirst()
实现:
这里如果不理解链表节点连接的建议画个双向链表来比对
//把当前的节点放到链表首位
private void putNodeFirst(ListNode node){
//这里建议画图好理解
node.front.next = node.next;
node.next.front = node.front;
//记录第一个节点
ListNode temp = head.next;
head.next = node;
node.front = head;
node.next = temp;
temp.front = node;
}
}
删除最后一个节点的方法 : deletLastNode()
//删除最后一个节点
private void deletLastNode(){
//先找到到最后一个节点即tail的上一个节点
ListNode lastNode = tail.front;
//然后我们将倒数第2个节点与tail连接那么倒数第二个节点就成了最后1个节点了
lastNode.front.next = tail;
tail.front = lastNode.front;
//将最后lastNode从map中移除
map.remove(lastNode.key);
}
get方法的实现:
先判断map中是否存在对应的key值,没有的话返回-1,有的话返回对应的value,然后将对应的节点放到首位
public int get(int key) {
if(map.containsKey(key)){
ListNode node1 = map.get(key);
putNodeFirst(node1);
return node1.value;
}else{
return -1;
}
}
完整代码解答:
//先定义一个节点类
class ListNode{
//它是一个双向链表
int key;
int value;
ListNode front;
ListNode next;
public ListNode(int key,int value){
this.key = key;
this.value = value;
}
}
class LRUCache {
int capacity;
//Key是数字,值为链表
Map<Integer,ListNode> map = new HashMap<>();
//设置1个链表的头和尾
ListNode head = new ListNode(0,0);
ListNode tail = new ListNode(0,0);
public LRUCache(int capacity) {
this.capacity = capacity;
//设置双向链表的连接
head.next = tail;
tail.front = head;
}
// 思路:
// 先判断map中是否存在对应的key值,没有的话返回-1,有的话返回对应的value,然后将对应的节点放到首位
public int get(int key) {
if(map.containsKey(key)){
ListNode node1 = map.get(key);
putNodeFirst(node1);
return node1.value;
}else{
return -1;
}
}
public void put(int key, int value) {
//先看该链表中有无当前的key,没有的话在添加之前要先确定容量
if(!map.containsKey(key)){
if(map.size() == capacity) deletLastNode();
//先保存第一个节点即head的下一个节点
ListNode temp = head.next;
//先定义要新添加的节点
ListNode newListNode = new ListNode(key,value);
//head的下一个节点即为第一个节点,因为是双向链表因此需要2次连接
head.next = newListNode;
newListNode.front = head;
//将temp连接到新的链表之后
newListNode.next = temp;
temp.front = newListNode;
//再将新的节点加入map
map.put(key,newListNode);
}else{
//如果map中有key的话,我们仅需要更改里面的value
//先拿到对应key的节点
ListNode list1 = map.get(key);
list1.value = value;
//因为我们做了1次修改,我们应该把修改的那个节点放在最前面
putNodeFirst(list1);
}
}
//删除最后一个节点
private void deletLastNode(){
//先找到到最后一个节点即tail的上一个节点
ListNode lastNode = tail.front;
//然后我们将倒数第2个节点与tail连接那么倒数第二个节点就成了最后1个节点了
lastNode.front.next = tail;
tail.front = lastNode.front;
//将最后lastNode从map中移除
map.remove(lastNode.key);
}
//把当前的节点放到链表首位
private void putNodeFirst(ListNode node){
//这里建议画图好理解
node.front.next = node.next;
node.next.front = node.front;
//记录第一个节点
ListNode temp = head.next;
head.next = node;
node.front = head;
node.next = temp;
temp.front = node;
}
}
二叉树的中序遍历(94)
这道题是简单题,同时也是树这个数据结构最基础的题,我们首先需要理解什么是中序遍历,(左,根,右),同时题上要求我们用一个数组来进行存储,因此我们需要定义一个数组。
扩展: 链接: (前序遍历 + 中序遍历 +后序遍历)
完整代码解答:
class Solution {
ArrayList<Integer> list = new ArrayList<>();
public List<Integer> inorderTraversal(TreeNode root) {
if(root != null){
//先左子节点
inorderTraversal(root.left);
//根节点
list.add(root.val);
inorderTraversal(root.right);
}
return list;
}
}