654.最大二叉树 leetcode链接
思考
题目要求
- 二叉树的根是数组中的最大元素。
- 左子树是通过数组中最大值左边部分构造出的最大二叉树。
- 右子树是通过数组中最大值右边部分构造出的最大二叉树。
构造树一般采用的是前序遍历,因为先构造中间节点,然后递归构造左子树和右子树。
递归三部曲:
1.明确递归方法的参数和返回类型
public TreeNode constructMaximumBinaryTree(int[] nums)
2.明确递归终止条件
//终止条件
if (nums.length == 1) {
return new TreeNode(nums[0]);
}
3.明确单层递归逻辑【中序】
(1)记录到数组中最大值maxValue及其下标maxIndex,并将最大值赋值给root节点的val
(2)根据题意,以maxIndex为分界点将数组分为左右两部分
(3)递归计算左边的最大值和右边的最大值
//中
int maxValue = 0;
int maxIndex = 0;
for (int i = 0; i < nums.length; i++) {
if (nums[i] > maxValue) {
maxValue = nums[i];
maxIndex = i;
}
}
TreeNode root = new TreeNode(maxValue);
//左
if (maxIndex > 0) {
int[] temp = new int[maxIndex];
for (int i = 0; i < maxIndex; i++) {
temp[i] = nums[i];
}
root.left = constructMaximumBinaryTree(temp);
}
//右
if (maxIndex < nums.length - 1) {
int[] temp = new int[nums.length - maxIndex - 1];
int j = 0;
for (int i = maxIndex + 1; i < nums.length; i++,j++) {
temp[j] = nums[i];
}
root.right = constructMaximumBinaryTree(temp);
}
return root;
代码展示
class Solution {
public TreeNode constructMaximumBinaryTree(int[] nums) {
//终止条件
if (nums.length == 1) {
return new TreeNode(nums[0]);
}
//中
int maxValue = 0;
int maxIndex = 0;
for (int i = 0; i < nums.length; i++) {
if (nums[i] > maxValue) {
maxValue = nums[i];
maxIndex = i;
}
}
TreeNode root = new TreeNode(maxValue);
//左
if (maxIndex > 0) {
int[] temp = new int[maxIndex];
for (int i = 0; i < maxIndex; i++) {
temp[i] = nums[i];
}
root.left = constructMaximumBinaryTree(temp);
}
//右
if (maxIndex < nums.length - 1) {
int[] temp = new int[nums.length - maxIndex - 1];
int j = 0;
for (int i = maxIndex + 1; i < nums.length; i++,j++) {
temp[j] = nums[i];
}
root.right = constructMaximumBinaryTree(temp);
}
return root;
}
}
class TreeNode {
int val;
TreeNode left;
TreeNode right;
public TreeNode() {
}
public TreeNode(int val) {
this.val = val;
}
public TreeNode(int val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}
总结
关键是理解题意,如题中给出的最大二叉树的定义
优化:可以通过下标索引直接在原数组上操作,这样可以节约时间和空间上的开销。
617.合并二叉树
思考
合并二叉树要考虑,相同位置的节点是否为空,如果为空就返回另一个节点的值赋值(这可以解决两个节点都为空和只有一个节点为空的情况),如果都不为空则返回二者之和。这里选择创建一个新的二叉树返回,不改变原来的二叉树
递归三部曲:
1.明确递归方法的参数和返回值
public TreeNode mergeTrees(TreeNode root1, TreeNode root2)
2.明确递归方法的终止条件
if (root1 == null) {
return root2;
}
if (root2 == null) {
return root1;
}
3.明确单层递归逻辑
//中
TreeNode root = new TreeNode();
root.val = root1.val + root2.val;
//左
root.left = mergeTrees(root1.left,root2.left);
//右
root.right = mergeTrees(root1.right,root2.right);
return root;
代码展示
class Solution {
public TreeNode mergeTrees(TreeNode root1, TreeNode root2) {
if (root1 == null) {
return root2;
}
if (root2 == null) {
return root1;
}
//中
TreeNode root = new TreeNode();
root.val = root1.val + root2.val;
//左
root.left = mergeTrees(root1.left,root2.left);
//右
root.right = mergeTrees(root1.right,root2.right);
return root;
}
}
class TreeNode {
int val;
TreeNode left;
TreeNode right;
public TreeNode() {
}
public TreeNode(int val) {
this.val = val;
}
public TreeNode(int val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}
总结
依然是创建二叉树的逻辑,不过在二叉树节点的值上有所不同
700.二叉搜索树中的搜索 leetcode链接
思考
二叉搜索树的搜索相对于普通二叉树搜索更加方便,代码逻辑基本相同。不过在原来普通二叉树的搜索中向左或向右搜索时添加了判断条件,减少了搜索的路径。
递归三部曲
1.明确递归方法的参数和返回值
public TreeNode searchBST(TreeNode root, int val)
2.明确递归方法的终止条件
if (root == null || root.val == val) {
return root;
}
3.明确单层递归逻辑
TreeNode result = null;
if (root.val < val) { //注意这里的条件
result = searchBST(root.right,val); //注意这里的逻辑 传入的是root.right 而不是root.left
}
if (root.val > val) {
result = searchBST(root.left,val);
}
return result;
代码展示
递归法
class Solution {
public TreeNode searchBST(TreeNode root, int val) {
if (root == null || root.val == val) {
return root;
}
TreeNode result = null;
if (root.val < val) {
result = searchBST(root.right,val);
}
if (root.val > val) {
result = searchBST(root.left,val);
}
return result;
}
}
class TreeNode {
int val;
TreeNode left;
TreeNode right;
public TreeNode() {
}
public TreeNode(int val) {
this.val = val;
}
public TreeNode(int val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
迭代法
本题使用 迭代法的代码也非常简洁明了
//迭代法
public TreeNode searchBST(TreeNode root, int val) {
while (root != null) {
if (val > root.val) {
root = root.right;
} else if (val < root.val) {
root = root.left;
}else {
return root;
}
}
return null;
}
总结
一提到二叉树遍历的迭代法,可能立刻想起使用栈来模拟深度遍历,使用队列来模拟广度遍历。
对于二叉搜索树可就不一样了,因为二叉搜索树的特殊性,也就是节点的有序性,可以不使用辅助栈或者队列就可以写出迭代法。
对于一般二叉树,递归过程中还有回溯的过程,例如走一个左方向的分支走到头了,那么要调头,在走右分支。
而对于二叉搜索树,不需要回溯的过程,因为节点的有序性就帮我们确定了搜索的方向。
————《代码随想录》
98.验证二叉搜索树 leetcode链接
思考
验证二叉树是否为二叉搜索树,即判断在中序遍历时前一个结点的值是否小于当前节点。可以使用暴力解法,将中序遍历的结果放到数组中,最后再判断数组是否单调递增。除此之外,也可以使用一个指针指向前节点,每遍历一个节点时做一次比较,具体逻辑看代码展示。
递归三部曲:
1.明确递归方法的参数和返回值
public boolean isValidBST(TreeNode root)
2.明确递归方法终止条件
if (root == null) {
return true;
}
3.明确单层递归逻辑
//左
boolean left = isValidBST(root.left);
if (preNode != null && preNode.val >= root.val) {
return false;
}
preNode = root;
//右
boolean right = isValidBST(root.right);
return right && left;
代码展示
class Solution {
private long minValue = Long.MIN_VALUE;
public boolean isValidBST(TreeNode root) {
if (root == null) {
return true;
}
boolean left = isValidBST(root.left);
if (minValue >= root.val) {
return false;
}
minValue = root.val;
boolean right = isValidBST(root.right);
return right && left;
}
}
class TreeNode {
int val;
TreeNode left;
TreeNode right;
public TreeNode() {
}
public TreeNode(int val) {
this.val = val;
}
public TreeNode(int val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}
总结
使用前置指针的方式比使用数组的方式和设置最小值的方法更方便。