算法通关村第九关——中序遍历与搜索树

1 中序遍历和搜索树原理

二叉搜索树按照中序遍历正好是一个递增序列。其比较规范的定义是:

  • 若它的左子树不为空,则左子树上所有节点的值均小于它的根节点的值;
  • 若它的右子树不为空,则右子树所有节点的值均大于它的根节点的值;
  • 它的左、右子树也分别为二叉搜索树,比如下面的例子:

在这里插入图片描述

这两棵树的中序遍历分别是[1, 2, 3, 4, 5, 6, 7, 8, 9][6, 7, 8, 9],都是二叉搜索树。

2 二叉搜索树中搜索特定值

力扣700题,给定二叉搜索树(BST)的根节点和一个值。 你需要在BST中找到节点值等于给定值的节点。 返回以该节点为根的子树。 如果节点不存在,则返回 NULL。

比如target为3,给定二叉搜索树:

			5
		   /  \
		  3    4
		 / \
         1   2

应该返回如下子树:

		  3  
		 / \
         1   2

2.1 递归实现

使用递归来实现,先来分析一下有哪些情况:

  • 如果根节点root === null或者root.val === target就直接返回根节点;
  • 如果target < root.val,说明比右子树的值小,去根节点的左子树进行查找searchBST(root.left, target);
  • 如果target > root.val,说明比左子树的值大,去根节点的右子树进行查找searchBST(root.right, target)

递归完整代码如下:

// 递归法
function searchBST(root, target) {
	// 如果根节点为空或者root.val === target,直接返回root
	if (root === null || root.val === target) {
		return root;
	}
	// 如果target < root.val,进入根节点的左子树查找
	// 如果target > root.val,进入根节点的右子树查找
	return target < root.val ? searchBST(root.left, target) : searchBST(root.right, target);
}

2.2 迭代实现

迭代逻辑:

  • 如果根节点root === null或者root.val !== target,进入下面的判断
    • 如果target < root.val,说明比右子树的值小,去根节点的左子树进行查找,root = root.left;
    • 如果target > root.val,说明比左子树的值大,去根节点的右子树进行查找,root = root.right

迭代完整代码如下:

// 迭代法
function searchBST(root, target) {
	// 如果根节点为空或者target !== root.val
	while (root !==null && target !== root.val) {
		// 如果target < root.val,进入根节点的左子树查找,root = root.left
		// 如果target > root.val,进入根节点的右子树查找,root = root.right
		root = (target < root.val ? root.left : root.right);
	}
	return root;
}

3 验证二叉搜索树

力扣98题,给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。有效二叉树定义如下:

  • 节点的左子树只包含 小于 当前节点的数。
  • 节点的右子树只包含 大于 当前节点的数。
  • 所有左子树和右子树自身必须也是二叉搜索树。

分析:根据题目以及中序遍历的特性,可以知道二叉搜索树中序遍历得到的序列是一个升序序列,要判断是否是一个有效二叉树,只需要在中序遍历的时候一边遍历一边检查当前节点的值是否大于前一个遍历到的节点值即可。

3.1 递归实现

递归实现,代码如下:

function isValidBST(root) {
	let pre = Number.MIN_SAFE_INTEGER;
	return validBST(root);

	function validBST(node) {
		if (node === null) {
			return true;
		}
		// 如果左子树某个元素不满足要求就退出
		if (!validBST(node.left)) {
			return false;
		}
		// 如果当前节点值≤中序遍历前一个节点的值,不能满足二叉搜索树条件
		if (node.val <= pre) {
			return false;
		}
		pre = node.val;
		return validBST(node.right);
	}
}

3.2 迭代实现

测试用例的最小节点有可能是javascript中的最小值,因此初始化preVal = -Infinity

function isValidBST(root) {
	const nodeStack= [];
	let preVal = -Infinity;

	while (nodeStack.length !== 0 || root !== null) {
		while (root !== null) {
			nodeStack.push(root);
			// 先遍历左子树
			root = root.left;
		}
		// 比较左子树中间根节点与前一个节点的值,如果小与前一个节点值,说明不是二叉搜索树
		root = nodeStack.pop();
		if (root.val <= preVal) {
			return false;
		}
		preVal = root.val;
		// 再遍历右子树
		root = root.right;
	}
	return true;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值