每日题单 · 2026-09-17

用法

每题先自己写 25 分钟(时间盒),卡住就找我要档位提示;做完把 [x] 勾上。 复盘题不写新笔记,直接在原文出处下方追加「二刷日期 + 一句话卡点」。

🆕 新题(codetop 前端岗频率榜)

题目难度频率状态
102. 二叉树的层序遍历中等40🔁(已刷过,重做)
146. LRU缓存机制中等38🔁(已刷过,重做)

🔁 复盘(vault 轮换池)

题目难度频率备注
实现 Trie (前缀树)中等1复盘 · 出处:GRD 前缀树
单词拆分中等1复盘 · 出处:GRD 前缀树

完成打卡

/**
 * @param {TreeNode} root
 * @return {number[][]}
 */
var levelOrder = function(root) {
    if(!root) return []
    const res = []
    const queue = [root]
    while(queue.length) {
        let len = queue.length
        const curr = []
        while(len--) {
            const node = queue.shift()
            curr.push(node.val)
            node.left && queue.push(node.left)
            node.right && queue.push(node.right)
        }
        res.push(curr)
    }
    return res
};
/**
 * 解法一 · ES6 Map 有序特性(快速实现)
 * @param {number} capacity
 */
var LRUCache = function(capacity) {
    this.map = new Map()
    this.capacity = capacity
};
 
LRUCache.prototype.get = function(key) {
    if(!this.map.has(key)) return -1
    let value = this.map.get(key)
    this.map.delete(key)
    this.map.set(key, value)
    return value
};
 
LRUCache.prototype.put = function(key, value) {
    if(this.map.has(key)) {
        this.map.delete(key)
    }
    this.map.set(key, value)
    if(this.map.size > this.capacity) {
        this.map.delete(this.map.keys().next().value)
    }
};
 
/**
 * 解法二 · 哈希表 + 双向链表(脱离语言特性的底层硬核实现,面试首推)
 */
class ListNode {
    constructor(key, val) {
        this.key = key
        this.val = val
        this.next = null
        this.prev = null
    }
}
 
var LRUCacheCustom = function(capacity) {
    this.capacity = capacity
    this.map = new Map()
    this.size = 0
 
    this.head = new ListNode()
    this.tail = new ListNode()
    this.head.next = this.tail
    this.tail.prev = this.head
};
 
LRUCacheCustom.prototype.addToHead = function(node) {
    node.next = this.head.next
    node.prev = this.head
    this.head.next.prev = node
    this.head.next = node
};
 
LRUCacheCustom.prototype.removeNode = function(node) {
    node.prev.next = node.next
    node.next.prev = node.prev
};
 
LRUCacheCustom.prototype.moveToHead = function(node) {
    this.removeNode(node)
    this.addToHead(node)
};
 
LRUCacheCustom.prototype.removeTail = function() {
    const node = this.tail.prev
    this.removeNode(node)
    return node
};
 
LRUCacheCustom.prototype.get = function(key) {
    const node = this.map.get(key)
    if (!node) return -1
    this.moveToHead(node)
    return node.val
};
 
LRUCacheCustom.prototype.put = function(key, value) {
    const node = this.map.get(key)
    if (node) {
        node.val = value
        this.moveToHead(node)
    } else {
        const newNode = new ListNode(key, value)
        this.map.set(key, newNode)
        this.addToHead(newNode)
        this.size++
        if (this.size > this.capacity) {
            const removenode = this.removeTail()
            this.map.delete(removenode.key)
            this.size--
        }
    }
};
/**
 * 208. 实现 Trie (前缀树)
 */
var Trie = function() {
    this.isEnd = false
    this.ch = {}
};
 
/** 
 * @param {string} word
 * @return {void}
 */
Trie.prototype.insert = function(word) {
    let node = this
    for(let c of word) {
        if(!node.ch[c]) {
            node.ch[c] = new Trie()
        }
        node = node.ch[c]
    }
    node.isEnd = true
};
 
Trie.prototype.searchPrefix = function(word) {
    let node = this
    for(let char of word ){
        if(node.ch[char]) {
            node = node.ch[char]
        } else {
            return null
        }
    }
    return node
}
 
/** 
 * @param {string} word
 * @return {boolean}
 */
Trie.prototype.search = function(word) {
    const node = this.searchPrefix(word)
    return node ? node.isEnd : false
};
 
/** 
 * @param {string} prefix
 * @return {boolean}
 */
Trie.prototype.startsWith = function(prefix) {
    const node = this.searchPrefix(prefix)
    return !!node
};
/**
 * 139. 单词拆分 (一维 DP 完全背包模型)
 * @param {string} s
 * @param {string[]} wordDict
 * @return {boolean}
 */
var wordBreak = function(s, wordDict) {
    const set = new Set(wordDict)
    const dp = new Array(s.length + 1).fill(false)
    dp[0] = true
    for (let right = 1; right < dp.length; right++) {
        for (let left = 0; left < right; left++) {
            if (dp[left] && set.has(s.slice(left, right))) {
                dp[right] = true
                break
            }
        }
    }
 
    return dp[s.length]
};