前言
又是学习LeetCode二叉树的新一天,今天主要来学习一下二叉搜索树的内容,希望博主记录的内容能够对大家有所帮助 ,一起加油吧朋友们!💪💪💪
二叉搜索树中的搜索
LeetCode题目链接
需要在给定的二叉搜索树(BST)中找到节点值为给定的整数值val的节点,返回以该节点为根的子树,节点不存在返回null

我们来梳理思路🤔🤔🤔
- 首先的话二叉搜索树的定义,二叉搜索树就是左子树的节点的值都比根节点的值要小,反之右子树的节点是值都比根节点的值要大
- 就每次判断当前节点的val是否为给定的val吧,不是的话就递归左右子树,逻辑比较简单🤔🤔🤔
直接来梳理递归三要素
1 2
| public TreeNode searchBST(TreeNode root, int val) {}
|
1 2
| if(root == null) return null;
|
1 2 3 4 5 6 7 8
| if(root.val == val) return root;
TreeNode leftResult = searchBST(root.left, val); if(leftResult != null) return leftResult; TreeNode rightResult = searchBST(root.right, val); return rightResult;
|
这里的迭代法我们不需要借助栈或者是队列来存储节点,因为二叉搜索树的话我们判断一个节点的值和目标值对比后我们就知道去往它的左子树还是右子树去搜索了,所以不需要来存储多余的处理节点🤔🤔🤔
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| class Solution { public TreeNode searchBST(TreeNode root, int val) { while(root != null){ if(root.val == val)return root; if(root.val > val){ root = root.left; }else{ root = root.right; } } return null; } }
|
验证二叉搜索树
判断一个给定的二叉树是否是二叉搜索树

首先给出博主写的一个错误示例,从中我们可以更好的分析出递归的三要素
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| class Solution { public boolean isValidBST(TreeNode root) { if(root.left == null && root.right == null) return true;
if(root.left.val > root.val || root.right.val < root.val) return false;
boolean left = isValidBST(root.left); if(!left)return false; return isValidBST(root.right); } }
|
这里存在一个比较明显的问题,就是当我的单层处理逻辑以为是每层判断左右子节点的值不符合范围就返回false,但是实际上每层满足左小右大,整体的二叉树不一定满足左小有大

所以我们需要调整单层处理逻辑,对于每个节点的判断应该去判断节点值和其上层的节点(上几层未知)的值进行判断,这也表示递归会进入到叶子节点的空节点进行判断,所以我们调整递归三要素如下🤔🤔🤔
1 2
| private boolean isValidBST(TreeNode root, Integer maxValue, Integer minValue){}
|
1
| if(root == null)return true;
|
1 2 3
| if((maxValue != null && root.val >= maxValue) ||(minValue != null && root.val <= minValue))return false;
return isValidBST(root.left, root.val, minValue) && isValidBST(root.right, maxValue, root.val);
|
递归的完整代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13
| class Solution { public boolean isValidBST(TreeNode root) { return isValidBST(root, null, null); } private boolean isValidBST(TreeNode root, Integer maxValue, Integer minValue){ if(root == null)return true;
if((maxValue != null && root.val >= maxValue) ||(minValue != null && root.val <= minValue))return false;
return isValidBST(root.left, root.val, minValue) && isValidBST(root.right, maxValue, root.val); } }
|
迭代方法的话我们也来进行迭代关键点分析🤔🤔🤔
1 2 3 4
| Stack<Object[]> stack = new Stack<>();
stack.push(new Object[] {root, null, null});
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| Object[] cur = stack.pop(); TreeNode node = (TreeNode) cur[0]; Integer maxValue = (Integer) cur[1]; Integer minValue = (Integer) cur[2];
if (node == null) continue;
if ((maxValue != null && node.val >= maxValue) || (minValue != null && node.val <= minValue)) { return false; }
stack.push(new Object[] {node.left, node.val, minValue}); stack.push(new Object[] {node.right, maxValue, node.val});
|
完整迭代代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| class Solution { public boolean isValidBST(TreeNode root) { Stack<Object[]> stack = new Stack<>(); stack.push(new Object[] {root, null, null});
while (!stack.isEmpty()) { Object[] cur = stack.pop(); TreeNode node = (TreeNode) cur[0]; Integer maxValue = (Integer) cur[1]; Integer minValue = (Integer) cur[2];
if (node == null) continue;
if ((maxValue != null && node.val >= maxValue) || (minValue != null && node.val <= minValue)) { return false; }
stack.push(new Object[] {node.left, node.val, minValue}); stack.push(new Object[] {node.right, maxValue, node.val}); }
return true; } }
|
二叉搜索树的最小绝对差
LeetCode题目链接
给你一棵所有节点为非负值的二叉搜索树,请你计算树中任意两节点的差的绝对值的最小值。

我们梳理下逻辑🤔🤔🤔
- 因为对于二叉搜索树的任何节点,所有左子树的节点小于它,而右子树的节点大于它,根据这个特性可以很方便地找到相邻节点的差值🤔
- 中序遍历结合二叉搜索树会使得按照节点值升序来对每个节点进行访问,这个过程中可以用一个变量来跟踪前一个节点值,然后用一个变量来存储最小差值,每次访问进行更新🤔
梳理完毕后我们来梳理递归三要素
1 2 3
| private Integer prev = -1; private int min = Integer.MAX_VALUE; private void inOrderTraversal(TreeNode root){}
|
1 2
| if(root == null) return;
|
1 2 3 4 5 6 7 8 9 10 11
| inOrderTraversal(root.left);
if(prev != null){ min = Math.min(min, Math.abs(root.val - prev)); } prev = root.val;
inOrderTraversal(root.right);
|
递归完整代码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| class Solution { private int prev = -1; private int min = Integer.MAX_VALUE; public int getMinimumDifference(TreeNode root) { inOrderTraversal(root); return min; }
private void inOrderTraversal(TreeNode root){ if(root == null) return;
inOrderTraversal(root.left);
if(prev != -1){ min = Math.min(min, Math.abs(root.val - prev)); } prev = root.val;
inOrderTraversal(root.right); } }
|
我们继续来梳理迭代的思路🤔🤔🤔
- 用栈来进行节点遍历
- 仍然用两个变量来进行前序节点值记录和最小差值记录
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| class Solution { public int getMinimumDifference(TreeNode root) { Stack<TreeNode> stack = new Stack<>(); TreeNode cur = root; int prev = -1; int min = Integer.MAX_VALUE;
while(!stack.isEmpty() || cur != null){ while(cur != null){ stack.push(cur); cur = cur.left; }
cur = stack.pop(); if (prev != -1) { min = Math.min(min, Math.abs(cur.val - prev)); } prev = cur.val;
cur = cur.right; } return min;
}
}
|
总结
今天就先学到这里,国庆假期越来越近,继续加油👊👊👊