刷题二叉树之LeetCode

148 阅读8分钟

1530. 好叶子节点对的数量

1530. 好叶子节点对的数量

/**
 * 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} distance
 * @return {number}
 */
/* 后序遍历 */
var countPairs = function(root, distance) {
    if (root == null) return 0;
    let res = 0;
    const dfs = (root) => {
        if (root == null) return [];
        /* 叶子节点 */
        if (root.left == null && root.right == null) return [0];
        const left = dfs(root.left).map(i => i + 1);
        const right = dfs(root.right).map(i => i + 1);
        /* 计算最短路径 */
        for (const l of left) {
            for (const r of right) {
                if (l + r <= distance) res++;
            }
        }

        return [...left, ...right];
    }
    dfs(root);
    return res;
};

剑指 Offer 55 - I. 二叉树的深度

剑指 Offer 55 - I. 二叉树的深度

/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number}
 */
/* 后序遍历 */
var maxDepth = function(root) {
    if (root == null) return 0;
    const dfs = (root) => {
        if (root == null) return 0;
        const left = dfs(root.left);
        const right = dfs(root.right);
        return Math.max(left, right) + 1;
    };
    return dfs(root);
};

101. 对称二叉树

101. 对称二叉树

/**
 * 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}
 */
var isSymmetric = function(root) {
    const check = (leftNode, rightNode) => {
        if (leftNode == null && rightNode == null) return true;
        if (leftNode == null || rightNode == null) return false;
        return leftNode.val == rightNode.val && check(leftNode.left, rightNode.right) && check(leftNode.right, rightNode.left);
    };
    return check(root, root);
};

226. 翻转二叉树

简单: 226. 翻转二叉树

/**
 * 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 {TreeNode}
 */
/* 很经典的二叉树问题 */
var invertTree = function(root) {
    if (root == null) return null;
    const left = invertTree(root.left);
    const right = invertTree(root.right);

    root.left = right;
    root.right = left;
    return root;
};

543. 二叉树的直径

543. 二叉树的直径

/**
 * 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 diameterOfBinaryTree = function(root) {
    if (root == null) return null;
    let res = 0;
    const dfs = (root) => {
        if (root == null) return 0;
        const left = dfs(root.left);
        const right = dfs(root.right);
        /* 取最大值 */
        res = Math.max(res, left+right);

        return Math.max(left, right) + 1;
    }
    dfs(root);
    return res;
};

971. 翻转二叉树以匹配先序遍历

971. 翻转二叉树以匹配先序遍历0

/**
 * 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[]} voyage
 * @return {number[]}
 */
var flipMatchVoyage = function(root, voyage) {
    if (root == null) return [-1];
    if (root.val !== voyage[0]) return [-1];
    let res = [];
    let i = 0;
    const dfs = (root) => {
        if (root == null) return;
        i++;
        /* 如果左树匹配 */
        if (root.left && root.left.val == voyage[i]) {
            dfs(root.left);
        }
        if (root.right && root.right.val == voyage[i]) {
            dfs(root.right);
            /* 右树完成之后,需要看看现在 pos 所在的值是否可以匹配左树,即是否先走右树再走左树,成立即当前的 root 节点就是需要进行翻转的节点 */
            if (root.left && root.left.val == voyage[i]) {
                res.push(root.val);
                dfs(root.left);
            }
        }
    }
    dfs(root);
    if (i < voyage.length) return [-1];
    return res;
}; 

面试题 04.06. 后继者

面试题 04.06. 后继者

/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */
/**
 * @param {TreeNode} root
 * @param {TreeNode} p
 * @return {TreeNode}
 */
/* 中序遍历 */
var inorderSuccessor = function(root, p) {
    if(root == null) {
        return null;
    }
    const arr = [];
    let res = 0;
    const dfs = (root) => { 
        if(root == null) return;
        dfs(root.left);
        arr.push(root);
        if(root == p) {
            res = arr.length;
        }
        dfs(root.right);
    }
    dfs(root);
    return arr[res];
};

144. 二叉树的前序遍历

144. 二叉树的前序遍历

/**
 * 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 preorderTraversal = function(root) {
    if (root == null) return [];
    const res = [];
    const dfs = (root) => {
        if (root == null) return;
        res.push(root.val);
        root.left && dfs(root.left);
        root.right && dfs(root.right);
    }
    dfs(root);
    return res;
};

230. 二叉搜索树中第K小的元素

230. 二叉搜索树中第K小的元素

/**
 * 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} k
 * @return {number}
 */
/* 中序遍历 */
var kthSmallest = function(root, k) {
    if (root == null) return null;
    const res = [];
    const dfs = (root) => {
        if (root == null) return;
        dfs(root.left);
        res.push(root.val);
        dfs(root.right);
    }
    dfs(root);
    return res[k - 1];
};

145. 二叉树的后序遍历

145. 二叉树的后序遍历

/**
 * 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 postorderTraversal = function(root) {
    if (root == null) return [];
    const res = [];
    const dfs = (root) => {
        if (root == null) return;
        dfs(root.left);
        dfs(root.right);
        res.push(root.val);
    }
    dfs(root);
    return res;
};

102. 二叉树的层序遍历

102. 二叉树的层序遍历

/**
 * 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 levelOrder = function(root) {
    if (root == null) return [];
    const res = [];
    const queue = [root];
    while (queue.length) {
        /* 记录当前层的节点数 */
        let length = queue.length;
        /* 存放每一层的节点 */
        let currentArr = [];
        for (let index = 0; index < length; index++) {
            /* 这里注意要用shift, 因为下面是push, 所以要取头部的 */
            const node = queue.shift();
            currentArr.push(node.val);
            /* 存放下一层的节点 */
            if (node.left) {
                queue.push(node.left);
            }
            if (node.right) {
                queue.push(node.right);
            }
        }
        res.push(currentArr);
    }
    return res;
};

236. 二叉树的最近公共祖先

236. 二叉树的最近公共祖先

/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */
/**
 * @param {TreeNode} root
 * @param {TreeNode} p
 * @param {TreeNode} q
 * @return {TreeNode}
 */
var lowestCommonAncestor = function(root, p, q) {
    if(root == null) return null;
    const dfs = (root) => {
        /* 确定递归终止条件 */
        if (root == null) {return null;}
        /* 这是其中一种情况, 如果root 等于其中某一个,那么,root就是要找到的最近的公共祖先 */
        if(root == p || root == q) {
            return root;
        }
        const left = dfs(root.left);
        const right = dfs(root.right);

        if(left && right) {
            /* 当这两个同时不为空,那么p,q 肯定就是在root的两侧,那么root就是我们要找的节点 */
            return root;
        }
        if (left == null) {
            return right;
        }
        return left;
    }
    return dfs(root);
}; 

103. 二叉树的锯齿形层序遍历

103. 二叉树的锯齿形层序遍历

/**
 * 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 zigzagLevelOrder = function(root) {
    if (root == null) return [];

    const queue = [root];
    let res = [];
    /* 设置一个开关 */
    let b = true;
    while (queue.length) {
        let length = queue.length;
        let curArr = [];
        for (let index = 0; index < length; index++) {
            const node = queue.shift();
            curArr.push(node.val);
            /* 新的一层 */
            if (node.left) {
                queue.push(node.left);
            }
            if (node.right) {
                queue.push(node.right);
            }
        }
        /* 进行反转 */
        if(!b) {
            curArr = curArr.reverse();
        }
        b = !b;
        res.push(curArr);
    }
    return res;
};

107. 二叉树的层序遍历 II

107. 二叉树的层序遍历 II

/**
 * 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 levelOrderBottom = function(root) {
    if (root == null) return [];

    const queue = [root];
    const res = [];
    while(queue.length) {
        const curArr = [];
        const length = queue.length;

        for (let index = 0; index < length; index++) {
            const node = queue.shift();
            curArr.push(node.val);
            if (node.left) {
                queue.push(node.left);
            }
            if (node.right) {
                queue.push(node.right);
            }
        }
        res.push(curArr);
    }
    return res.reverse();
};

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

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 == null) {
        return new TreeNode(val);
    }
    if (root.val >= val) {
        /* 如果当前的节点大于等于要插入的节点,那么就插入左子树 */
        root.left = insertIntoBST(root.left, val);
    } else {
        root.right = insertIntoBST(root.right, val);
    }

    return root;
};

108. 将有序数组转换为二叉搜索树

108. 将有序数组转换为二叉搜索树

/**
 * 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 {number[]} nums
 * @return {TreeNode}
 */
var sortedArrayToBST = function(nums) {
    if (nums.length === 0) return null;
    const dfs = (nums, left, right) => {
        // 条件限制
        if (left > right) return null;
        // 找到中点
        const mid = Math.floor(left + (right - left) / 2);
        const root = new TreeNode(nums[mid]);
        // 左子树
        root.left = dfs(nums, left, mid - 1);
        // 右子树
        root.right = dfs(nums, mid + 1, right);
        return root;
    }
    return dfs(nums, 0, nums.length - 1);
};

1382. 将二叉搜索树变平衡

1382. 将二叉搜索树变平衡

/**
 * 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 {TreeNode}
 */
/* 
    上一个题目,是一个有序数组转化为平衡二叉树
    思路: 
    1, 先把BST 中序遍历,生成一个有序数组
    2, 再把这个有序数组转化为平衡BST二叉树
*/
var balanceBST = function(root) {
    if (root == null) return null;
    const arr = [];
    const inorder = (root) => {
        if (root == null) return;
        inorder(root.left);
        arr.push(root.val);
        inorder(root.right);
    }
    inorder(root);
    const buildDfs = (arr, left, right) => {
        if (left > right) return null;

        // zhong
        const mid = Math.floor(left + (right - left) / 2);
        const root = new TreeNode(arr[mid]);
        root.left = buildDfs(arr, left, mid - 1);
        root.right = buildDfs(arr, mid + 1, right);
        return root;
    }
    return buildDfs(arr, 0, arr.length - 1);
};

100. 相同的树

100. 相同的树

/**
 * 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} p
 * @param {TreeNode} q
 * @return {boolean}
 */
var isSameTree = function(p, q) {
    if (p == null && q == null) {
        return true;
    } else if (p == null || q == null) {
        return false;
    } else if (p.val !== q.val) {
        return false;
    } else {
        return isSameTree(p.left, q.left) && isSameTree(p.right, q.right);
    }
};

111. 二叉树的最小深度

111. 二叉树的最小深度

/**
 * 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}
 */
/* 这个使用BFS 更好理解 */
var minDepth = function(root) {
    if (root == null) return 0;

    const queue = [root];
    let depth = 1;
    while(queue.length) {
        const length = queue.length;
        for (let index = 0; index < length; index++) {
            const node = queue.shift();

            if (node.left == null && node.right == null) {
                return depth;
            }

            if (node.left) {
                queue.push(node.left);
            }
            if (node.right) {
                queue.push(node.right)
            }
            
        }
        depth += 1;
    }
    return depth;
};

112. 路径总和

112. 路径总和

/**
 * 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} targetSum
 * @return {boolean}
 */
var hasPathSum = function(root, targetSum) {
    if(root == null) {
        return false;
    }
    if (root.left == null && root.right == null) {
        return root.val === targetSum;
    }
    return hasPathSum(root.left, targetSum - root.val) || hasPathSum(root.right, targetSum - root.val);
};

235. 二叉搜索树的最近公共祖先

235. 二叉搜索树的最近公共祖先

/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */

/**
 * @param {TreeNode} root
 * @param {TreeNode} p
 * @param {TreeNode} q
 * @return {TreeNode}
 */
var lowestCommonAncestor = function(root, p, q) {
    if (root == null) return null;
    const dfs = (root) => {
        if (root == null) {
            return null;
        }
        /* 这是其中一种情况, 如果root 等于其中某一个,那么,root就是要找到的最近的公共祖先 */
        if (root.val == p.val || root.val == q.val) {
            return root;
        }
        const left = dfs(root.left);
        const right = dfs(root.right);

        if (left && right) {
            return root;
        }
        if (left == null) {
            return right;
        }
        return left;
    }
    return dfs(root);
};

257. 二叉树的所有路径

257. 二叉树的所有路径

/**
 * 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 {string[]}
 */
var binaryTreePaths = function(root) {
    if (root == null) return [];
    const res = [];
    const dfs = (root, arr) => {
        if (root == null) return;
        arr.push(root.val);
        if (root.left == null && root.right == null) {
            const str = arr.join('->');
            res.push(str);
        }
        dfs(root.left, arr);
        dfs(root.right, arr);
        /* 回溯 */
        arr.pop();
    }
    dfs(root, []);
    return res;
};

404. 左叶子之和

简单

404. 左叶子之和

/**
 * 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 sumOfLeftLeaves = function(root) {
    if (root == null) return 0;
    let num = 0;
    const dfs = (root) => {
        if (root == null) return;
        if (root.left !== null && root.left.left == null && root.left.right == null) {
            num = num + root.left.val;
        }
        dfs(root.left);
        dfs(root.right);
    }
    dfs(root);
    return num;
};

501. 二叉搜索树中的众数

501. 二叉搜索树中的众数

/**
 * 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 findMode = function(root) {
    if (root == null) return [];
    let res = [];
    let pre; /* 当前数字 */
    let preNum; /* 当前数字的数量 */
    let max = 0;
    const dfs = (root) => {
        if(root == null) return;

        if (root.left) dfs(root.left);
        /* 处理判断条件 */
        if (root.val == pre) {
            preNum++;
        } else {
            pre = root.val;
            preNum = 1;
        }
        if (preNum > max) {
            max = preNum;
            /* 替换为新的众数 */
            res = [root.val];
        } else if (preNum == max) {
            res.push(root.val);
        }
        if (root.right) dfs(root.right);
    }
    dfs(root);
    return res;
};

530. 二叉搜索树的最小绝对差

530. 二叉搜索树的最小绝对差

/**
 * 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 getMinimumDifference = function(root) {
    let min = Number.MAX_SAFE_INTEGER;
    let pre = -1;
    const dfs = (root) => {
        if (root == null) return;
        if(root.left) dfs(root.left);
        /* 逻辑 */
        if (pre == -1) {
            pre = root.val;
        } else {
            min = Math.min(root.val - pre, min);
            pre = root.val;
        }
        
        if(root.right) dfs(root.right);
    }
    dfs(root);
    return min;
};

572. 另一棵树的子树

572. 另一棵树的子树

/**
 * 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 {TreeNode} subRoot
 * @return {boolean}
 */
var isSubtree = function(root, subRoot) {

    let bool = true
    let res = false
    let subnode = subRoot
    function tra(n1, n2) {
        if (n1 && n2) {
            if (n1.val === n2.val) {
                tra(n1.left, n2.left)
                tra(n1.right, n2.right)
            } else {
                bool = false
            }
        } else {
            if ((!n2 && !n1)) {
                return ;
            } else {
                bool = false
            }
        }
    }
    function traverse(node) {
        // 如果已经找到相同子树了(res === true)就直接返回不再递归了
        // 防止重复的叶子,导致res置false
        if (!node || res) {
            return ;
        }
        if (node.val === subnode.val) {
            // 每次准备dfs子树时,先将标志置true
            // 因为树中可能有重复val的叶子 
            bool = true
            tra(node, subnode)
            res = bool
        }
        traverse(node.left)
        traverse(node.right)
    }
    traverse(root)
    return res
};

606. 根据二叉树创建字符串

简单

606. 根据二叉树创建字符串

/**
 * 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 {string}
 */
var tree2str = function(root) {
    if (root == null) return '';
    
    const dfs = (root) => {
        if(root == null) return '';
        /* 找到叶子节点 */
        if (root.left == null && root.right == null) {
            return `${root.val}`;
        }
        let left, right;
        if(root.left && !root.right) {
            left = `(${dfs(root.left)})`;
            right = '';
        } else {
            left = root.left ? `(${dfs(root.left)})` : '()';
            right = `(${dfs(root.right)})`;
        }
        
        return `${root.val}${left}${right}`;
    }
    
    return dfs(root);
};