Leetcode100 二叉树的中序遍历

思路

这题的关键是同时满足两个要求:

  • O(1) 查找 :所以要用 HashMap。
  • 维护最近使用顺序 :所以要用 双向链表。

只用 HashMap 可以 O(1) 找到 key,但不知道哪个是"最近最少使用"的;

只用链表可以维护顺序,但查找是 O(n)。

所以要把两者结合起来。

数据结构设计

维护一个 双向链表,链表头部表示最近使用的,尾部表示最久未使用的。

同时维护一个 HashMap<Integer, Node>,用来 O(1) 找到某个 key 对应的节点。

  • get(key):

    • 如果 key 不存在,返回 -1。
    • 如果存在,把对应节点移到链表头部,表示最近使用过,然后返回它的值。
  • put(key, value):

    • 如果 key 已存在,更新node里的value值,并把节点移到链表头部。
    • 如果 key 不存在:
      • 先新建节点,插入链表头部,并放入 map。
      • 再判断如果超过容量,就删除链表尾部节点,同时从 map 中移除。

movetohead:把当前链表中有的节点移到最前面 先removenode再addtohead

addtohead:把新建的节点插入到头部

removetail:移除tail.prev即最后一个节点

removenode:移除链表中指定节点

初始:head <-> tail

head <-> 1 <-> tail

假设当前是 head <-> A <-> tail,要插入新节点 X:注意顺序

复制代码
执行前:  head <-> A <-> tail

第1步 node.next = head.next     X.next = A
第2步 node.prev = head          X.prev = head
第3步 head.next.prev = node     A.prev = X
第4步 head.next = node          head.next = X

执行后:  head <-> X <-> A <-> tail
removeNode(node)

假设当前是 head <-> A <-> B <-> C <-> tail,要删除 B:

复制代码
执行前:  A <-> B <-> C

第1步 A.next = C     (B的前驱指向B的后继)
第2步 C.prev = A     (B的后继指向B的前驱)

执行后:  A <-> C      (B被摘掉)
moveToHead(node)

就是先摘掉,再插到头部。比如:

复制代码
head <-> A <-> B <-> C <-> tail

moveToHead(B):

先 removeNode(B):  head <-> A <-> C <-> tail
再 addToHead(B):   head <-> B <-> A <-> C <-> tail
removeTail()

直接取 tail.prev,就是最久未使用的节点,然后把它摘掉。

class LRUCache {

复制代码
class Node{

    int key;

    int value;

    Node prev;

    Node next;

    public Node(int key,int value ){

        this.key=key;

        this.value=value;

    }

}

private final int capacity;

private final Map<Integer,Node> map;

private final Node head;

private final Node tail;



public LRUCache(int capacity) {

    this.capacity=capacity;

    this.map=new HashMap<>();

    head=new Node(0,0);

    tail=new Node(0,0);

    head.next=tail;

    tail.prev=head;

}

public int get(int key) {

    if(!map.containsKey(key))

        return -1;

    Node node=map.get(key);

    movetohead(node);

    return node.value;

}

public void put(int key, int value) {

    if(map.containsKey(key)){

        Node node=map.get(key);

        node.value=value;

        movetohead(node);

        return;

    }

    Node node=new Node(key,value);

    map.put(key,node);

    addtohead(node);

    if(map.size()>capacity){

       Node lastnode=tail.prev;

       removetail();

       map.remove(lastnode.key);

       return;

    }

}



private void addtohead(Node node){

    head.next.prev=node;

    node.prev=head;

    node.next=head.next;

    head.next=node;

}

private void removenode(Node node){

    node.prev.next=node.next;

    node.next.prev=node.prev;

}

private void movetohead(Node node){

    removenode(node);

    addtohead(node);

}

private Node removetail(){

    Node lastnode=tail.prev;

    removenode(lastnode);

    return lastnode;

}

}

/**

  • Your LRUCache object will be instantiated and called as such:

  • LRUCache obj = new LRUCache(capacity);

  • int param_1 = obj.get(key);

  • obj.put(key,value);

*/

二叉树的中序遍历

中序遍历:左根右

思路:

1.递归 dfs(左子树) 根 dfs(右子树)

  1. 先递归遍历左子树
  2. 再访问当前节点(把值加入结果)
  3. 最后递归遍历右子树

2.用栈模拟递归stack

  1. 一路向左:从当前节点开始,不断往左走,把沿途节点全部压栈。这样栈顶就是最左边的节点(应该最先访问)。
  2. 弹栈访问:弹出栈顶节点,把它的值加入结果(这就是"根"的位置)。
  3. 转向右边 :把当前指针移到这个节点的右子树,然后重复第1步。
    栈思路:只要当前节点不为空,或者栈也不为空,就先一路把左节点push进栈,当某一时刻为null时,将栈顶元素出栈,并且加入结果数组,然后指针转向右子树,重复循环,继续一路把左节点push进栈

保证了左 根 右

class Solution {

public List inorderTraversal(TreeNode root) {

ArrayList res=new ArrayList<>();

ArrayDeque stack=new ArrayDeque<>();

TreeNode cur=root;

while(cur!=null||!stack.isEmpty()){

while(cur!=null){

stack.push(cur);

cur=cur.left;

}

cur=stack.pop();

res.add(cur.val);

cur=cur.right;

}

return res;

}

}

相关推荐
砚底藏山河1 小时前
量化实战:行情数据 Schema 演进与向后兼容
java·python·金融·maven
专业程序开发源1 小时前
flask动漫推荐系统32319-计算机课程设计、毕业设计
java·spring boot·后端·django·flask·php·课程设计
根目录下的猫1 小时前
ROS 2 C++(rclcpp)版本,实现话题订阅、话题发布,以及完整编译运行流程
开发语言·c++·算法
FYKJ_20101 小时前
springboot手工蜀绣在线销售系统60947-计算机课程设计、毕业设计
java·spring boot·后端·python·mysql·spark·课程设计
vx_Biye_Design1 小时前
springboot老年人用药智能管理系统38605-计算机课程设计、毕业设计
java·spring boot·后端·python·django·课程设计·express
QQ_21696290961 小时前
基于C#(Asp.net)电竞陪玩信息管理系统的设计与实现
java·大数据·spring boot·微信小程序·c#·云计算·asp.net
vx_Biye_Design1 小时前
springbootNBA数据分析系统平台42434-计算机课程设计、毕业设计
java·vue.js·spring boot·python·django·课程设计·express
Q26433650231 小时前
【有源码】基于springboot的知识产权管理系统-知识产权咨询问答管理系统-知识产权价值评估管理系统
java·spring boot·mysql·spring·毕业设计·javaweb·课程设计
大侠归来3 小时前
C 语言 | 在函数中操作数组
c语言·c++·算法