代码随想录算法训练营第二十天 | 654.最大二叉树、617.合并二叉树 、700.二叉搜索树中的搜索 、98.验证二叉搜索树
654.最大二叉树
二叉树的递归构造
思路:构造树一般采用的是前序遍历,因为先构造中间节点,然后递归构造左子树和右子树。
class Solution {
public TreeNode constructMaximumBinaryTree(int[] nums) {
return constructMaximumBinaryTree1(nums, 0, nums.length);
}
public TreeNode constructMaximumBinaryTree1(int[] nums, int leftIndex, int rightIndex) {
// 确定终止条件
if (rightIndex - leftIndex < 1) { // 没有元素了
return null;
}
if (rightIndex - leftIndex == 1) { // 只有一个元素
return new TreeNode(nums[leftIndex]);
}
// 先要找到数组中最大的值和对应的下标, 最大的值构造根节点,下标用来下一步分割数组
int maxIndex = leftIndex; // 最大值所在位置
int maxVal = nums[maxIndex]; // 最大值
for (int i = leftIndex + 1; i < rightIndex; i++) {
if (nums[i] > maxVal){
maxVal = nums[i];
maxIndex = i;
}
}
TreeNode root = new TreeNode(maxVal);
// 根据 maxIndex 划分左右子树
// 不需要判断下标是因为以下代码是允许空指针进入递归的
// 最大值所在的下标左区间构造左子树
root.left = constructMaximumBinaryTree1(nums, leftIndex, maxIndex);
// 最大值所在的下标右区间 构造右子树
root.right = constructMaximumBinaryTree1(nums, maxIndex + 1, rightIndex);
return root;
}
}
617.合并二叉树
二叉树的递归构造
思路:对两颗二叉树进行操作,同样采用前序遍历进行构造。
class Solution {
public TreeNode mergeTrees(TreeNode root1, TreeNode root2) {
// 终止条件
if (root1 == null) return root2;
if (root2 == null) return root1;
root1.val += root2.val; // 中
root1.left = mergeTrees(root1.left, root2.left); // 左
root1.right = mergeTrees(root1.right, root2.right); // 右
return root1; // 就在 root1 上进行修改,不构造新的树
}
}
700.二叉搜索树中的搜索
二叉搜索树的使用
思路:初遇二叉搜索树。值得注意的是二叉搜索树的构造规则(左孩子小于父节点,右孩子大于父节点)使得遍历时不再需要考虑选择前中后序。迭代法更是重量级!
/**
* 递归法
*/
class Solution {
public TreeNode searchBST(TreeNode root, int val) {
if (root == null || root.val == val) return root;
TreeNode result = new TreeNode();
if (val < root.val) {
result = searchBST(root.left, val);
}
if (val > root.val) {
result = searchBST(root.right, val);
}
return result;
}
}
/**
* 迭代法
*/
class Solution {
public TreeNode searchBST(TreeNode root, int val) {
while (root != null) {
if (val < root.val) {
root = root.left;
} else if (val > root.val) {
root = root.right;
} else {
return root;
}
}
return null;
}
}
98.验证二叉搜索树
二叉搜索树的使用
思路:遇到搜索树,第一反应中序遍历,因为可以利用相关特性。
/**
* 递归法
*/
class Solution {
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;
// 右
boolean right = isValidBST(root.right);
return right;
}
}
/**
* 迭代法
*/
class Solution {
public boolean isValidBST(TreeNode root) {
if (root == null) {
return true;
}
Stack<TreeNode> stack = new Stack<>();
TreeNode pre = null;
while (root != null || !stack.isEmpty()) {
while (root != null) {
stack.push(root);
root = root.left;// 左
}
// 中,处理
TreeNode pop = stack.pop();
if (pre != null && pop.val <= pre.val) {
return false;
}
pre = pop;
root = pop.right;// 右
}
return true;
}
}
/**
* 简洁实现·递归解法
*/
class Solution {
public boolean isValidBST(TreeNode root) {
return validBST(Long.MIN_VALUE, Long.MAX_VALUE, root);
}
boolean validBST(long lower, long upper, TreeNode root) {
if (root == null) return true;
if (root.val <= lower || root.val >= upper) return false;
return validBST(lower, root.val, root.left) && validBST(root.val, upper, root.right);
}
}
// 简洁实现·中序遍历
class Solution {
private long prev = Long.MIN_VALUE;
public boolean isValidBST(TreeNode root) {
if (root == null) {
return true;
}
if (!isValidBST(root.left)) {
return false;
}
if (root.val <= prev) { // 不满足二叉搜索树条件
return false;
}
prev = root.val;
return isValidBST(root.right);
}
}