前言:
这两天在某站看了左神的算法课,发现受益匪浅,发现好的老师,总是可以用言简意赅的语言,一下子找到问题的重点,在这里和大家分享一下。
二叉树例子:
后面题目的讲述都以这颗二叉树为例:
题目一:请实现一个方法,可以判断一颗二叉树是否为搜索二叉树
PS: 搜索二叉树满足所有的子树都是头节点大于左节点,且头节点小于右节点
搜索二叉树的中序遍历是升序的!
所以我们可以利用这一点,来判断是否是一个搜索二叉树,代码如下
// 声明一个全局变量,在遍历的过程中和他比较,一旦比它小,就不是升序的
// 比它大,则把值传递给它
public static int value = Integer.MIN_VALUE;
public static boolean isSearchBinary(TreeNode root) {
Stack<TreeNode> stack = new Stack<>();
while (root != null || !stack.isEmpty()) {
while (root != null) {
stack.push(root);
root = root.left;
}
root = stack.pop();
if (root.val < value)
return false;
value = root.val;
root = root.right;
}
return true;
}
还提供一种方法如下
/**
* 定义一个类用来描述二叉树返回的信息
* isBST 标识这棵树是否是搜索二叉树
* min 这棵树的最小值
* max 这棵树的最大值
*/
public static class ReturnData{
boolean isBST;
int min;
int max;
public ReturnData(boolean isBST, int min, int max) {}
}
public static ReturnData process(TreeNode root) {
// base case也就是递归的出口
if (root == null)
// 这个时候其实最大最小值定义多少都不合适,我们直接返回空,在后续的代码进行判断
return null;
// 分别向我的左数和右数要信息
ReturnData leftData = process(root.left);
ReturnData rightData = process(root.right);
// 所以这棵树是bst的条件应该为,左右树都是BST,且左数的最大值小于root的值,且右数的最小值大于root的值
int min = root.val;
int max = root.val;
if (leftData != null) {
min = Math.min(min, leftData.min);
max = Math.max(max, leftData.max);
}
if (rightData != null) {
min = Math.min(min, rightData.min);
max = Math.max(max, rightData.max);
}
boolean isBST = true;
if (leftData != null && (!leftData.isBST || leftData.max >= root.val)) {
isBST = false;
}
if (rightData != null && (!rightData.isBST || rightData.min <= root.val)) {
isBST = false;
}
return new ReturnData(isBST, min, max);
}
题目二: 实现一个方法,可以判断一棵树是否为完全二叉树
首先,我们看下什么是完全二叉树
- 严格定义:设二叉树的深度为,除第层外,其它各层的结点数都达到最大个数,第层所有的结点都连续集中在最左边。
- 直观理解:一棵完全二叉树从根节点开始,每一层都尽可能填满节点,只有最下面一层的节点可以不满,但这些节点必须集中在左边。
思路如下:
由于完全二叉树的特性,我们采用层序遍历
- 如果碰到一个节点,有右无左,直接返回false
- 如果碰到了第一个叶子节点,那后面的都要是叶子节点了
/**
* 该方法用来判断一颗二叉树是否为完全二叉树
* @param root
*/
public static boolean isCBT(TreeNode root) {
// 创建一个队列用于层序遍历一个二叉树
LinkedList<TreeNode> queue = new LinkedList<>();
// 该标记用于判断是否已经遇到了第一个叶子节点了
boolean leaf = false;
TreeNode l = null;
TreeNode r = null;
if (root != null)
queue.add(root);
while (!queue.isEmpty()) {
TreeNode node = queue.pollFirst();
// 如果碰到一个节点有右无左,直接返回false即可
if (node.right != null && node.left == null)
return false;
// 如果标识为true的情况下,如果碰到一个节点有子节点,也返回false即可
if (leaf && (node.left != null || node.right != null))
return false;
// 左右节点加入到队列中方便后续的层序遍历
if (node.left != null)
queue.addLast(node.left);
if (node.right != null)
queue.addLast(node.right);
// 这里标识已经碰到了第一个叶子节点了,标识改为true
if (node.left == null)
leaf = true;
}
return true;
}