DAILY DOCDAILY DOC
Rust
Node
Notes
Ubuntu
Leetcode
  • it-tools
  • excalidraw
  • linux-command
Rust
Node
Notes
Ubuntu
Leetcode
  • it-tools
  • excalidraw
  • linux-command
  • Array

    • 数组
    • 二分查找
    • moveZeros
  • Dynamic-programming

    • 动态规划
  • 刷题指南
  • String

    • 字符串
  • bitwise-operator

    • 位运算符
  • heap
  • history

    • [1014] 最佳观光组合
    • [1022] 从根到叶的二进制数之和
    • [104] 二叉树的最大深度
    • [11] 盛最多水的容器
    • [110] 平衡二叉树
    • [1227] 飞机座位分配概率
    • [129] 求根节点到叶节点数字之和
    • [1306] 跳跃游戏 III
    • [148] 排序链表
    • 155.最小栈
    • [165] 比较版本号
    • 1763. 最长的美好子字符串
    • [1870] 准时到达的列车最小时速
    • [199] 二叉树的右视图
    • [21] 合并两个有序链表
    • 215.数组中的第 k 个最大元素
    • [2306] 公司命名
    • [234] 回文链表
    • [2516] 每种字符至少取 K 个
    • [316] 去除重复字母
    • [3171] 找到按位或最接近 K 的子数组
    • [322] 零钱兑换
    • [41] 缺失的第一个正数
    • [44] 通配符匹配
    • [494] 目标和
    • [509] 斐波那契数
    • [518] 零钱兑换 II
    • [62] 不同路径
    • [676] 实现一个魔法字典
    • 70 爬楼梯
    • [718] 最长重复子数组
    • [78] 子集
    • [82] 删除排序链表中的重复元素 II
    • [871] 最低加油次数
    • [88] 合并两个有序数组
    • [887] 鸡蛋掉落
    • 958.二叉树的完全性检验
    • [98] 验证二叉搜索树
    • [983] 最低票价
    • leetcode practice
    • 约瑟夫问题
    • 移除重复节点
  • linked-list

    • 706. 设计哈希映射
    • 链表
  • stack

    • stack
  • tree

    • Tree Traversal
    • 二叉树的最近公共祖先
    • 二叉树
    • 题目
  • leetCode 刷题
  • 回溯
  • 排序算法

题目

460. LFU 缓存

details
class Node {
    constructor(key, value) {
        this.key = key;
        this.value = value;
        this.freq = 1;
        this.prev = null;
        this.next = null;
    }
}

class DoublyLinkedList {
    constructor() {
        this.head = new Node(null, null);
        this.tail = new Node(null, null);
        this.head.next = this.tail;
        this.tail.prev = this.head;
    }

    addNode(node) {
        let realTail = this.tail.prev;
        realTail.next = node;
        node.prev = realTail;
        node.next = this.tail;
        this.tail.prev = node;
    }

    removeNode(node) {
        let prev = node.prev;
        let next = node.next;
        prev.next = next;
        next.prev = prev;
    }

    isEmpty() {
        return this.head.next === this.tail;
    }
}

class LFUCache {
    constructor(capacity) {
        this.capacity = capacity;
        this.size = 0;
        this.minFreq = 0;
        this.cache = new Map();
        this.freqMap = new Map();
    }

    get(key) {
        if (!this.cache.has(key)) {
            return -1;
        }
        let node = this.cache.get(key);
        this._update(node);
        return node.value;
    }

    put(key, value) {
        if (this.capacity === 0) return;

        if (this.cache.has(key)) {
            let node = this.cache.get(key);
            node.value = value;
            this._update(node);
        } else {
            if (this.size >= this.capacity) {
                let minFreqList = this.freqMap.get(this.minFreq);
                let nodeToRemove = minFreqList.head.next;
                this.cache.delete(nodeToRemove.key);
                minFreqList.removeNode(nodeToRemove);
                this.size--;
            }
            let newNode = new Node(key, value);
            this.cache.set(key, newNode);
            if (!this.freqMap.has(1)) {
                this.freqMap.set(1, new DoublyLinkedList());
            }
            this.freqMap.get(1).addNode(newNode);
            this.minFreq = 1;
            this.size++;
        }
    }

    _update(node) {
        let freq = node.freq;
        let list = this.freqMap.get(freq);
        list.removeNode(node);
        if (freq === this.minFreq && list.isEmpty()) {
            this.minFreq++;
        }
        node.freq++;
        if (!this.freqMap.has(node.freq)) {
            this.freqMap.set(node.freq, new DoublyLinkedList());
        }
        this.freqMap.get(node.freq).addNode(node);
    }
}

98. 验证二叉搜索树

details
/*
 * 98. 验证二叉搜索树
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {boolean}
 */

// 中序遍历的时候能拿到有序的 ,判断到不是 递增的时候 return  false
var isValidBST = function (root) {
    let preMax = -Infinity;

    let ans = true;
    traverse(root);
    return ans;

    function traverse(root) {
        if (!root) return;
        traverse(root.left);
        console.log(root.val);
        if (root.val > preMax) {
            preMax = root.val;
        } else {
            // 不是递增的,
            ans = false;
            return;
        }
        traverse(root.right);
    }
};

// 判断 左子树小于 根节点,柚子树 大于根节点
var isValidBST = function (root) {
    return traverse(root, null, null);
    function traverse(root, min, max) {
        if (!root) return true;
        if (min != null && root.val <= min.val) return false;
        if (max != null && root.val >= max.val) return false;

        return traverse(root.left, min, root) && traverse(root.right, root, max);
    }
};

146. LRU 缓存

details
class ListNode {
    constructor(key, value) {
        this.key = key;
        this.value = value;
        this.prev = null;
        this.next = null;
    }
}

class LRUCache {

constructor(capacity) {
this.capacity = capacity;
this.map = new Map();
this.head = new ListNode(null, null);
this.tail = new ListNode(null, null);
this.head.next = this.tail;
this.tail.prev = this.head;
}

    _remove(node) {
        let prev = node.prev;
        let next = node.next;
        prev.next = next;
        next.prev = prev;
    }

    _add(node) {
        let realTail = this.tail.prev;
        realTail.next = node;
        node.prev = realTail;
        node.next = this.tail;
        this.tail.prev = node;
    }

    get(key) {
        if (this.map.has(key)) {
            let node = this.map.get(key);
            this._remove(node);
            this._add(node);
            return node.value;
        } else {
            return -1;
        }
    }

    put(key, value) {
        if (this.map.has(key)) {
            this._remove(this.map.get(key));
        }

        let newNode = new ListNode(key, value);
        this._add(newNode);
        this.map.set(key, newNode);

        if (this.map.size > this.capacity) {
            let firstNode = this.head.next;
            this._remove(firstNode);
            this.map.delete(firstNode.key);
        }
    }

}

剑指 Offer II 044. 二叉树每层的最大值

details
/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * 剑指 Offer II 044. 二叉树每层的最大值
 * @param {TreeNode} root
 * @return {number[]}
 */
var largestValues = function(root) {
  //
  const ans = [];
  if (!root) {
    return ans;
  }
  //
  const queue = [root];
  while (queue.length) {
    const len = queue.length;
    let i = 0;
    let levelMax = -Number.MAX_SAFE_INTEGER;
    while (i < len) {
      i++;
      const item = queue.shift();
      if (!item) {
        continue;
      }
      levelMax = Math.max(item.val, levelMax);
      //
      item.left && queue.push(item.left);
      item.right && queue.push(item.right);
    }
    levelMax !== -Number.MAX_SAFE_INTEGER && ans.push(levelMax);
  }

  return ans;
};

102. 二叉树的层序遍历

details
/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * 102. 二叉树的层序遍历
 * @param {TreeNode} root
 * @return {number[][]}
 */
var levelOrder = function (root) {
    if (root === null) return [];

    let result = [];
    const queue = [root];
    while (queue.length) {
        let level = [];
        const len = queue.length;
        for (let i = 0; i < len; i++) {
            const item = queue.shift();
            level.push(item.val);
            if (item.left) queue.push(item.left);
            if (item.right) queue.push(item.right);
        }
        result.push(level);
    }
    return result;
};

剑指 Offer II 044. 二叉树每层的最大值

details
/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * 剑指 Offer II 044. 二叉树每层的最大值
 * @param {TreeNode} root
 * @return {number[]}
 */
var largestValues = function(root) {
  //
  const ans = [];
  if (!root) {
    return ans;
  }
  //
  const queue = [root];
  while (queue.length) {
    const len = queue.length;
    let i = 0;
    let levelMax = -Number.MAX_SAFE_INTEGER;
    while (i < len) {
      i++;
      const item = queue.shift();
      if (!item) {
        continue;
      }
      levelMax = Math.max(item.val, levelMax);
      //
      item.left && queue.push(item.left);
      item.right && queue.push(item.right);
    }
    levelMax !== -Number.MAX_SAFE_INTEGER && ans.push(levelMax);
  }

return ans;
};

104. 二叉树的最大深度

details
/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * 104. 二叉树的最大深度
 * @param {TreeNode} root
 * @return {number}
 */

var maxDepth = function(root) {
    let depth = 0
    let ans = 0
    traverse(root);
    return ans;

    function traverse(root) {
        if(!root) {
            ans = Math.max(ans,depth)
            return
        }
        depth++
        traverse(root.left)
        traverse(root.right)
        depth--
    }
};
// console.log(ans)


/**
 * 通过子树高度推导
*/
var maxDepth = function(root) {
  if (!root) return 0;
  const maxLeft = maxDepth(root.left);
  const maxRight = maxDepth(root.right);
  return Math.max(maxLeft, maxRight) + 1;
};

105. 从前序与中序遍历序列构造二叉树

details
/*
 * 105. 从前序与中序遍历序列构造二叉树
 */
/**
 * @param {number[]} preOrder
 * @param {number[]} inOrder
 * @return {TreeNode}
 */
var buildTree = function(preOrder, inOrder) {
  const map = Object.create(null);
  // 遍历一遍 中序遍历结果 得到hash 表,用hash 表查找节点对应的 左子树 跟右子树
  for (let i = 0; i < inOrder.length; i++) {
    map[inOrder[i]] = i;
  }
  const len = preOrder.length - 1;

return traverse(preOrder, inOrder, 0, len, 0, len);

function traverse(preOrder, inOrder, preStart, preEnd, inStart, inEnd) {
if (preStart > preEnd || inStart > inEnd) return null;
// 前序遍历第一个元素就是 根节点
const root = new TreeNode(preOrder[preStart]);
// 找到 root 在中序遍历中的元素
const rootIndex = map[root.val];
const leftSubTreeSize = rootIndex - inStart;
// 递归地构造左子树,并连接到根节点
// 先序遍历中「从 左边界+1 开始的 size_left_subtree」个元素就对应了中序遍历中「从 左边界 开始到 根节点定位-1」的元素

    root.left = traverse(preOrder, inOrder, preStart + 1, preStart + leftSubTreeSize, inStart, rootIndex - 1);

    // 递归地构造右子树,并连接到根节点
    // 先序遍历中「从 左边界+1+左子树节点数目 开始到 右边界」的元素就对应了中序遍历中「从 根节点定位+1 到 右边界」的元素

    root.right = traverse(preOrder, inOrder, preStart + leftSubTreeSize + 1, preEnd, rootIndex + 1, inEnd);
    return root;

}
};

// Definition for a binary tree node.
function TreeNode(val, left, right) {
this.val = val === undefined ? 0 : val;
this.left = left === undefined ? null : left;
this.right = right === undefined ? null : right;
}

99. 恢复二叉搜索树

details
/*
 * 99. 恢复二叉搜索树
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {void} Do not return anything, modify root in-place instead.
 */
var recoverTree = function(root) {
  // 恰好有2个节点,找到这2个节点,交换位置即可
  let first = null;
  let second = null;
  let prev = new TreeNode(-Infinity);

  traverse(root);

  // 找到元素了,交换位置
  const temp = first.val;
  first.val = second.val;
  second.val = temp;

  function traverse(root) {
    if (!root) return null;
    traverse(root.left);
    // 中序遍历代码位置,找出那两个节点
    if (root.val < prev.val) {
      // root 不符合有序性
      if (first === null) {
        // 第一个错位节点是 prev
        first = prev;
      }
      // 第二个错位节点是 root
      second = root;
    }
    prev = root;

    traverse(root.right);
  }
};

function TreeNode(val, left, right) {
  this.val = val === undefined ? 0 : val;
  this.left = left === undefined ? null : left;
  this.right = right === undefined ? null : right;
}

124. 二叉树中的最大路径和

details
/*
 * 124. 二叉树中的最大路径和
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number}
 */
var maxPathSum = function(root) {
  let ans = -Number.MAX_SAFE_INTEGER;
  traverse(root);
  return ans;

function traverse(root) {
if (!root) return 0;
const leftMax = Math.max(0, traverse(root.left));
const rightMax = Math.max(0, traverse(root.right));

    // 当前节点路径
    const newPath = leftMax + root.val + rightMax;
    ans = Math.max(ans, newPath);

    // 单边最大贡献
    // 至少包含一个节点 当前节点
    return root.val + Math.max(leftMax, rightMax);

}
};

700. 二叉搜索树中的搜索

details
/*
 * 700. 二叉搜索树中的搜索
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @param {number} val
 * @return {TreeNode}
 */
var searchBST = function(root, val) {
  if (!root) return null;
  if (root.val === val) {
    return root;
  } else if (root.val > val) {
    return searchBST(root.left, val);
  } else {
    return searchBST(root.right, val);
  }
};

35. 搜索插入位置

details
/*
 * 35. 搜索插入位置
 * @param {number[]} nums
 * @param {number} target
 * @return {number}
 */

// 问题转换为 查找第一个大于等于 target 的元素
var searchInsert = function(nums, target) {
let left = 0;
let right = nums.length - 1;
// 最大的一个元素,则插入到尾部
let ans = nums.length;
while (left <= right) {
let mid = (left + (right - left) / 2) >> 0;
if (nums[mid] >= target) {
ans = mid;
right = mid - 1;
} else {
left = mid + 1;
}
}
return ans;
};

701. 二叉搜索树中的插入操作

details
/*
 * 701. 二叉搜索树中的插入操作
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @param {number} val
 * @return {TreeNode}
 */
var insertIntoBST = function(root, val) {
  //
  if (!root) return new TreeNode(val);

  if (root.val < val) {
    root.right = insertIntoBST(root.right, val);
  } else {
    root.left = insertIntoBST(root.left, val);
  }
  return root;
};

function TreeNode(val, left, right) {
  this.val = val === undefined ? 0 : val;
  this.left = left === undefined ? null : left;
  this.right = right === undefined ? null : right;
}

450. 删除二叉搜索树中的节点

details
/*
 * 450. 删除二叉搜索树中的节点
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @param {number} key
 * @return {TreeNode}
 */
var deleteNode = function(root, key) {
  if (!root) return null;
  if (root.val > key) {
    root.left = deleteNode(root.left, key);
  } else if (root.val < key) {
    root.right = deleteNode(root.right, key);
  } else {
    // 单边只有一个节点
    if (root.left === null) return root.right;
    if (root.right === null) return root.left;
    // 找到右子树最小的节点
    const minNode = getLeftMost(root.right);
    root.val = minNode.val;
    root.right = deleteNode(root.right, minNode.val);
  }
  return root;

function getLeftMost(root) {
while (root.left !== null) {
root = root.left;
}
return root;
}
};

297. 二叉树的序列化与反序列化

details
/*
 * 297. 二叉树的序列化与反序列化
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */

/**
 * Encodes a tree to a single string.
 *
 * @param {TreeNode} root
 * @return {string}
 */
var serialize = function(root) {
  const ans = [];
  traverse(root);
  function traverse(root) {
    if (!root) {
      ans.push(null);
      return null;
    }
    ans.push(root.val);
    traverse(root.left);
    traverse(root.right);
  }

  return ans.toString();
};

/**
 * Decodes your encoded data to tree.
 *
 * @param {string} data
 * @return {TreeNode}
 */
var deserialize = function(data) {
  const arr = data.split(',');

  return traverse(arr);

  function traverse() {
    if (!arr.length) return null;
    const val = arr.shift();
    if (!val) return null;
    const root = new TreeNode(val);
    root.left = traverse();
    root.right = traverse();
    return root;
  }
};

/**
 * Your functions will be called as such:
 * deserialize(serialize(root));
 */

function TreeNode(val) {
  this.val = val;
  this.left = this.right = null;
}

Last Updated:
Contributors: rosendo
Prev
二叉树