二叉树算法的设计的总路线:明确一个节点要做的事情,然后剩下的事抛给框架。
void traverse(TreeNode root) {
// root 需要做什么?在这做。
// 其他的不用 root 操心,抛给框架
traverse(root.left);
traverse(root.right);
}
PS:关于写算法的框架,是很重要的,直接决定了我们思考的方向,强烈建议先看看我的博客文章:学习数据结构的框架思维
举两个简单的例子体会一下这个思路,热热身。
1. 如何把二叉树所有的节点中的值加一?
void plusOne(TreeNode root) {
if (root == null) return;
root.val += 1;
plusOne(root.left);
plusOne(root.right);
}
2. 如何判断两棵二叉树是否完全相同?
boolean isSameTree(TreeNode root1, TreeNode root2) {
// 都为空的话,显然相同
if (root1 == null && root2 == null) return true;
// 一个为空,一个非空,显然不同
if (root1 == null || root2 == null) return false;
// 两个都非空,但 val 不一样也不行
if (root1.val != root2.val) return false;
// root1 和 root2 该比的都比完了
return isSameTree(root1.left, root2.left)
&& isSameTree(root1.right, root2.right);
}
借助框架,上面这两个例子不难理解吧?如果可以理解,那么所有二叉树算法你都能解决。
二叉搜索树(Binary Search Tree,简称 BST)是一种很常用的的二叉树。它的定义是:一个二叉树中,任意节点的值要大于等于左子树所有节点的值,且要小于等于右边子树的所有节点的值。
如下就是一个符合定义的 BST:
下面实现 BST 的基础操作:判断 BST 的合法性、增、删、查。其中“删”和“判断合法性”略微复杂。
零、判断 BST 的合法性
这里是有坑的哦,我们按照刚才的思路,每个节点自己要做的事不就是比较自己和左右孩子吗?看起来应该这样写代码:
boolean isValidBST(TreeNode root) {
if (root == null) return true;
if (root.left != null && root.val <= root.left.val)