vlambda博客
学习文章列表

二十一:判断二叉树是否是二叉查找树?

二叉查找树:左子树所有结点值均小于它的根结点的值;右子树所有结点值均大于它的根结点值。


别名:二叉搜索树、二叉排序树。

算法一


思路:

  • 根据二叉搜索树特性。

  • 判断当前结点是否是空结点,如果是返回true(空结点属于二叉搜索树)。

  • 判断当前结点值是否在[min,max](开区间)之间,如果不在返回false。

  • 如果在区间内,则递归检查左右子树是否满足条件。

/** * @description 二叉树是否是二叉搜索树 * @param {*} root 二叉树 */function isValidBST(root) { /** * @param {*} root 二叉树   * @param {*} min 区间最小值,默认为无穷小 * @param {*} max 区间最大值,默认为无穷大 */ function dfs(root, min = -Infinity, max = Infinity) { // 如果空结点返回true if (!root) return true; // 如果不在区间内,返回false if (root.value <= min || root.value >= max) return false; // 递归左结点,将max值更改为当前结点的值 // 同理递归右节点,将min值更改为当前结点的值 return dfs(root.left, min, root.value) && dfs(root.right, root.value, max); } return dfs(root);}

算法二

思路:

  • 根据二叉树中序遍历特性,依次输出结点值是有序序列。

  • 根据二叉查找树特性,只需要判断该序列是否是递增序列。

  • 声明一个变量用来记录上一个结点的值,默认值为无穷小。

  • 中序遍历(左/中/右):判断当前节点值是否小于等于前一个结点值,如果是返回false。


递归中序遍历:

/** * @description 二叉树是否是二叉搜索树 (中序遍历) * @param {*} root 二叉树 */function isValidBST(root) {  // 默认值为无穷小 let preVal = -Infinity; function dfs(root) { if (!root) return true; const left = dfs(root.left); // 如果上一个结点值大于等于当前结点的值,返回false if (preVal >= root.val) return false; preVal = root.val; const right = dfs(root.right); // 返回最终结果 return left && right; } return dfs(root);}


非递归中序遍历:

/** * @description 二叉树是否是二叉搜索树 (中序遍历) * @param {*} root 二叉树 */function isValidBST(root) { const stack = []; // 上一个结点的值,默认无穷小 let preVal = -Infinity; while (stack.length || root) { while (root) {      // 入栈 stack.push(root); root = root.left; }    // 出栈 root = stack.pop(); // 如果上一个结点值大于等于当前结点的值,返回false if (preVal >= root.val) return false; preVal = root.val; root = root.right; } // 遍历结束,说明是二叉搜索树 return true}