验证二叉搜索树
给定一个二叉树,判断其是否是一个有效的二叉搜索树。
假设一个二叉搜索树具有如下特征:
- 节点的左子树只包含小于当前节点的数。
- 节点的右子树只包含大于当前节点的数。
- 所有左子树和右子树自身必须也是二叉搜索树
坑
不能单纯的比较左节点小于中间节点,右节点大于中间节点就完事了。
要比较的是 左子树所有节点小于中间节点,右子树所有节点大于中间节点
这个需要定义一个全局遍历,用来比较遍历的节点,是否符合二叉树的特点
代码
代码使用中序遍历,
先找到最左边的叶子节点,赋值给max,然后采用左中右,将这个max(左)和其父节点(中)对比,然后中赋值给max,再去对比右子树
对比过程中,会先找到右子树的最左边的叶子节点来对比这个max,确保符合二叉搜索树
TreeNode max;
public boolean isValidBST(TreeNode root) {
if (root==null){
return true;
}
// 左
boolean left = isValidBST(root.left);
if (!left) {
return false;
}
// 中
if (max != null && root.val <= max.val) {
return false;
}
max=root;
// 右
return isValidBST(root.right);
}
二叉搜索树的最小绝对差
给你一棵所有节点为非负值的二叉搜索树,请你计算树中任意两节点的差的绝对值的最小值。
二叉搜索树上求什么最值,求差值之类的,都要思考一下二叉搜索树可是有序的,要利用好这一特点
使用递归法,用一个pre节点记录一下cur节点的前一个节点。因为二叉树是有序的,所以采用左中右的递归遍历时,当前cur节点的val值一定大于前一个pre节点的val值
代码
TreeNode pre;// 记录上一个遍历的结点
int result = Integer.MAX_VALUE;
public int getMinimumDifference(TreeNode root) {
if(root==null)return 0;
traversal(root);
return result;
}
public void traversal(TreeNode root){
if(root==null)return;
//左
traversal(root.left);
//中
if(pre!=null){
result = Math.min(result,root.val-pre.val);
}
pre = root;
//右
traversal(root.right);
}
二叉搜索树中的众数
给定一个有相同值的二叉搜索树(BST),找出 BST 中的所有众数(出现频率最高的元素)。
假定 BST 有如下定义:
- 结点左子树中所含结点的值小于等于当前结点的值
- 结点右子树中所含结点的值大于等于当前结点的值
- 左子树和右子树都是二叉搜索树
例如:
输入:root = [1,null,2,2]
输出:[2]
- 如果这个树是非二叉搜索树
可以把这个树都遍历了,用map统计频率
把统计的出来的出现频率(即map中的value)排个序
取前面高频的元素
- 二叉搜索树,中序遍历就是有序的
用pre记录上一个节点,数值相同,节点肯定是相邻的
使用count记录出现的次数,然后用maxCount记录count的最大值
当maxCount==count时,元素添加到list中
当maxCount<count时,先将list清空,再将次元素添加到list中
代码
public static int[] findMode(TreeNode root) {
HashMap<Integer, Integer> map = new HashMap<>();
ArrayList<Integer> list = new ArrayList<>();
if (root==null) return list.stream().mapToInt(Integer::intValue).toArray();
//获得二叉树中各个值出现的频率
search(root,map);
List<Map.Entry<Integer, Integer>> mapList = map.entrySet().stream()
.sorted((c1, c2) -> c2.getValue().compareTo(c1.getValue()))
.collect(Collectors.toList());
list.add(mapList.get(0).getKey());//频率最高的树
for (int i = 1; i < mapList.size(); i++) {
if (mapList.get(i).getValue()==mapList.get(0).getValue()){
list.add(mapList.get(i).getKey());
}else {
break;
}
}
return list.stream().mapToInt(Integer::intValue).toArray();
}
private static void search(TreeNode root, HashMap<Integer, Integer> map) {
if (root==null) return;
map.put(root.val,map.getOrDefault(root.val,0)+1);
search(root.left,map);
search(root.right,map);
}
//利用二叉树的特点
ArrayList<Integer> list_;
int count;
TreeNode pre;
int maxCount;
public int[] findMode_(TreeNode root) {
list_ = new ArrayList<>();
maxCount = 0;
count = 0;
pre = null;
findMode1_(root);
return list_.stream().mapToInt(Integer::intValue).toArray();
}
private void findMode1_(TreeNode root) {
if (root==null) return;
findMode1_(root.left);
//中
if (pre==null||pre.val!= root.val){
count=1;
}else {
count++;
}
if (count>maxCount){
list_.clear();
list_.add(root.val);
maxCount=count;
}else if (count==maxCount){
list_.add(root.val);
}
pre=root;
findMode1_(root.right);
}