Problem: 98. 验证二叉搜索树
思路
最近做二叉树的题目比较多,这里面涉及到的主要是各种各样的递归问题。以这题为例复习和总结一下二叉树的递归问题。
本题的目标是验证二叉树是否为二叉搜索树。
方法一
朴素来看,要验证是二叉搜索树,我们需要保证左子树、右子树都是二叉搜索树,以及当前节点的值大于左子树的最大值,小于右子树的最小值。
这样,我们定义一个函数,其返回值是当前子树的最小值和最大值,用作比较目的。我们定义空子树的最小值为正无穷大,最大值为负无穷大,这样一定能够使得其父节点满足二叉搜索树性质,而且也为二叉搜索树。
然后,对于非空子树,我们先判断其是否满足二叉搜索树性质,如果不满足,则问题的答案就是false
。如果满足,我们把更新当前子树的最大最小值。最小值设为左子树的最小值(和当前节点值对比,防止左节点为空),最大值设为右子树的最大值(同理对比当前节点)。
当递归完成时,我们就可以找到是否有子树不满足二叉搜索树性质,若全部满足则为二叉搜索树。
方法二
可以看到,前一个方法需要经常创建最大最小值对,造成了一定的空间开销。
注意到二叉搜索树还有一个性质,也就是其中序遍历是单调序列。
如果我们利用二叉搜索树的性质,把函数的返回值设为当前子树是否为二叉搜索树,并记录前一个节点的值,通过中序遍历,我们就能判断是否为二叉搜索树。
具体过程见代码。
递归
递归的题目我认为本质是这样的:
递归终止条件时是正确的,然后前一层在假设子问题正确后运用算法能保持正确性。类似于数学归纳法。
换一种说法就是:
- 递归终止条件的正确性:当问题规模缩小到最简单的情况时,递归能够直接给出正确的结果。
- 递归关系的正确性:假设对更小规模的子问题的求解是正确的,通过递归关系能够正确地求解原问题。
递归问题除了关注终止条件、子问题和当前问题的关系以外,我认为还需要关注递归函数返回了什么,参数是什么,维持了什么性质。从这些切入点入手,递归问题就更容易思考。
递归时的数据传递可以用返回值,参数或者全局变量。我认为能够利用递归性质时最好使用返回值。难以观察递归性质时可以用全局变量,但是全局变量会影响可读性和可维护性。参数更适合作为对函数外无影响的条件。
Code
1 | /** |
1 | class Solution { |