1.知识点
2.刷题
654.最大二叉树
LeetCode链接 654. 最大二叉树 - 力扣(LeetCode)
题目描述:
方法1:递归
package daimasuixiangshuati.day19_erchashu;
/**
* @Author LeiGe
* @Date 2023/11/20
* @Description todo
*/
public class ZuiDaErChaShu654_1 {
/**
* 方法1:dfs-递归-前序遍历
* 1.先找到数组中的最大值,构建为当前节点
* 2.最大值左边区间构建左子树
* 3.最大值右边区间构建右子树
*
* @param nums
* @return
*/
public TreeNode constructMaximumBinaryTree(int[] nums) {
int left = 0;
int right = nums.length - 1;
return dfs(nums, left, right);
}
private TreeNode dfs(int[] nums, int left, int right) {
if (left > right) {
return null;
}
//找到当前区间内最大值的索引,同时也是将这个数组分开的边界
int bond = findMaxIndex(nums, left, right);
//构建当前节点
TreeNode root = new TreeNode(nums[bond]);
//构建左子树,右子树
TreeNode leftTreeNode = dfs(nums, left, bond - 1);
TreeNode rightTreeNode = dfs(nums, bond + 1, right);
root.left = leftTreeNode;
root.right = rightTreeNode;
return root;
}
/**
* 寻找数组中left-right区间内最大值的索引
*
* @param nums
* @param left
* @param right
* @return
*/
private int findMaxIndex(int[] nums, int left, int right) {
int max = Integer.MIN_VALUE;
int maxIndex = left;
for (int i = left; i <= right; i++) {
if (nums[i] > max) {
max = nums[i];
maxIndex = i;
}
}
return maxIndex;
}
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode() {
}
TreeNode(int val) {
this.val = val;
}
TreeNode(int val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}
}
方法2:单调栈
package daimasuixiangshuati.day19_erchashu;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Stack;
/**
* @Author LeiGe
* @Date 2023/11/20
* @Description todo
*/
public class ZuiDaErChaShu654_2 {
/**
* 方法2:单调栈递减栈:栈顶是最小值
* 1.方法1中寻找区间内最大值,会将数组中元素多次遍历,时间复杂度O(N^2)
* 2.通过一个单调递减栈,可以减少多次遍历数组中的元素
* 3.单调栈操作:插入元素x,栈顶元素y
* 3.1如果x小于y,则y.right=x,压栈
* 3.2如果x大于y,则x.left=y,出栈
* 4.栈底元素为低下根节点
* 参考:
* https://leetcode.cn/problems/maximum-binary-tree/solutions/1762400/zhua-wa-mou-si-by-muse-77-myd7/
*
* @param nums
* @return
*/
public TreeNode constructMaximumBinaryTree(int[] nums) {
Stack<TreeNode> stack = new Stack<>();
Deque<TreeNode> deque = new ArrayDeque();
deque.peek();
deque.peekLast();
deque.peekFirst();
for (int num : nums) {
//数组值对应的节点
TreeNode node = new TreeNode(num);
while (!stack.isEmpty()) {
TreeNode topNode = stack.peek();
//当前元素小于栈顶元素,压栈,
if (topNode.val > node.val) {
stack.push(node);
topNode.right = node;
break;
} else {//当前元素大于栈顶元素,弹栈
stack.pop();
node.left = topNode;
}
}
if (stack.isEmpty()) {
stack.push(node);
}
}
//栈底元素为最终的根节点
while (stack.size() > 1) {
stack.pop();
}
return stack.peek();
}
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode() {
}
TreeNode(int val) {
this.val = val;
}
TreeNode(int val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}
}
617.合并二叉树
LeetCode链接 617. 合并二叉树 - 力扣(LeetCode)
题目描述:
方法1:递归+构建新树
package daimasuixiangshuati.day19_erchashu;
/**
* @Author LeiGe
* @Date 2023/12/3
* @Description todo
*/
public class ErBingErChaShu617_1 {
/**
* 方法1:dfs+递归-构建一个新树-前序遍历
* 1.二叉树的前序,中序,后序遍历都可以
*
* @param root1
* @param root2
* @return
*/
public TreeNode mergeTrees(TreeNode root1, TreeNode root2) {
return dfs1(root1, root2);
}
private TreeNode dfs1(TreeNode root1, TreeNode root2) {
//baseCase
if (root1 == null && root2 == null) {
return null;
}
if (root1 == null) {
return root2;
}
if (root2 == null) {
return root1;
}
//左子树
TreeNode left = dfs1(root1.left, root2.left);
//右子树
TreeNode right = dfs1(root1.right, root2.right);
//构建新节点
return new TreeNode(root1.val + root2.val, left, right);
}
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode() {
}
TreeNode(int val) {
this.val = val;
}
TreeNode(int val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}
}
方法2:递归+返回其中一个树
package daimasuixiangshuati.day19_erchashu;
/**
* @Author LeiGe
* @Date 2023/12/3
* @Description todo
*/
public class ErBingErChaShu617_2 {
/**
* 方法2:dfs+递归-返回其中一个树-前序遍历
* 1.二叉树的前序,中序,后序遍历都可以
*
* @param root1
* @param root2
* @return
*/
public TreeNode mergeTrees(TreeNode root1, TreeNode root2) {
return dfs2(root1, root2);
}
private TreeNode dfs2(TreeNode root1, TreeNode root2) {
//baseCase
if (root1 == null && root2 == null) {
return null;
}
if (root1 == null) {
return root2;
}
if (root2 == null) {
return root1;
}
//左子树
TreeNode left = dfs2(root1.left, root2.left);
//右子树
TreeNode right = dfs2(root1.right, root2.right);
//返回其中一个树
root1.val = root1.val + root2.val;
root1.left = left;
root1.right = right;
return root1;
}
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode() {
}
TreeNode(int val) {
this.val = val;
}
TreeNode(int val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}
}
方法3:bfs+队列
package daimasuixiangshuati.day19_erchashu;
import java.util.LinkedList;
/**
* @Author LeiGe
* @Date 2023/12/3
* @Description todo
*/
public class ErBingErChaShu617_3 {
/**
* 方法3:bfs+队列
*
* @param root1
* @param root2
* @return
*/
public TreeNode mergeTrees(TreeNode root1, TreeNode root2) {
if (root1 == null && root2 == null) {
return null;
}
if (root1 == null) {
return root2;
}
if (root2 == null) {
return root1;
}
TreeNode merged = new TreeNode(root1.val + root2.val);
LinkedList<TreeNode> queue = new LinkedList<>();
LinkedList<TreeNode> queue1 = new LinkedList<>();
LinkedList<TreeNode> queue2 = new LinkedList<>();
queue.addLast(merged);
queue1.addLast(root1);
queue2.addLast(root2);
while (!queue1.isEmpty() && !queue2.isEmpty()) {
TreeNode node = queue.poll();
TreeNode node1 = queue1.poll();
TreeNode node2 = queue2.poll();
TreeNode left1 = node1.left;
TreeNode left2 = node2.left;
TreeNode right1 = node1.right;
TreeNode right2 = node2.right;
// 处理两颗树的左子树
if (left1 != null || left2 != null) {
// 如果两颗树的左子树都不为空,加入队列
if (left1 != null && left2 != null) {
TreeNode left = new TreeNode(left1.val + left2.val);
node.left = left;
queue.addLast(left);
queue1.addLast(left1);
queue2.addLast(left2);
}
// 如果一颗树的左子树不为null,直接赋值
else if (left1 != null) {
node.left = left1;
} else if (left2 != null) {
node.left = left2;
}
}
// 相同逻辑处理右子树
if (right1 != null || right2 != null) {
if (right1 != null && right2 != null) {
TreeNode right = new TreeNode(right1.val + right2.val);
node.right = right;
queue.addLast(right);
queue1.addLast(right1);
queue2.addLast(right2);
} else if (right1 != null) {
node.right = right1;
} else if (right2 != null) {
node.right = right2;
}
}
}
return merged;
}
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode() {
}
TreeNode(int val) {
this.val = val;
}
TreeNode(int val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}
}
700.二叉搜索树中的搜索
LeetCode链接 700. 二叉搜索树中的搜索 - 力扣(LeetCode)
题目描述:
方法1:普通二叉树+dfs
package daimasuixiangshuati.day19_erchashu;
/**
* @Author LeiGe
* @Date 2023/12/6
* @Description todo
*/
public class ErChaSouSuoShuZhongDeSouSuo700_1 {
/**
* 方法1:dfs递归:普通二叉树
*
* @param root
* @param val
* @return
*/
public TreeNode searchBST(TreeNode root, int val) {
return dfs1(root, val);
}
private TreeNode dfs1(TreeNode root, int val) {
//baseCase
if (root == null || root.val == val) {
return root;
}
TreeNode left = dfs1(root.left, val);
if (left != null) {
return left;
}
return dfs1(root.right, val);
}
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode() {
}
TreeNode(int val) {
this.val = val;
}
TreeNode(int val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}
}
方法2:搜索二叉树+dfs
package daimasuixiangshuati.day19_erchashu;
/**
* @Author LeiGe
* @Date 2023/12/6
* @Description todo
*/
public class ErChaSouSuoShuZhongDeSouSuo700_2 {
/**
* 方法2:dfs递归,利用二叉搜索树特点,优化
* 1.如果当前节点的值大于要找的val,左子树,否则右子树
*
* @param root
* @param val
* @return
*/
public TreeNode searchBST(TreeNode root, int val) {
return dfs2(root, val);
}
private TreeNode dfs2(TreeNode root, int val) {
if (root == null || root.val == val) {
return root;
}
if (val < root.val) {
return dfs2(root.left, val);
} else {
return dfs2(root.right, val);
}
}
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode() {
}
TreeNode(int val) {
this.val = val;
}
TreeNode(int val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}
}
方法3:普通二叉树+迭代
package daimasuixiangshuati.day19_erchashu;
import java.util.Stack;
/**
* @Author LeiGe
* @Date 2023/12/6
* @Description todo
*/
public class ErChaSouSuoShuZhongDeSouSuo700_3 {
/**
* 方法3:迭代法
* 迭代:普通二叉树
*
* @param root
* @param val
* @return
*/
public TreeNode searchBST(TreeNode root, int val) {
if (root == null || root.val == val) {
return root;
}
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
while (!stack.isEmpty()) {
TreeNode pop = stack.pop();
if (pop.val == val) {
return pop;
}
if (pop.right != null) {
stack.push(pop.right);
}
if (pop.left != null) {
stack.push(pop.left);
}
}
return null;
}
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode() {
}
TreeNode(int val) {
this.val = val;
}
TreeNode(int val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}
}
方法4:搜索二叉树+迭代
package daimasuixiangshuati.day19_erchashu;
import java.util.Stack;
/**
* @Author LeiGe
* @Date 2023/12/6
* @Description todo
*/
public class ErChaSouSuoShuZhongDeSouSuo700_4 {
/**
* 方法4:迭代法
* 迭代:利用二叉搜索树特点,优化,可以不需要栈
*
* @param root
* @param val
* @return
*/
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;
}
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode() {
}
TreeNode(int val) {
this.val = val;
}
TreeNode(int val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}
}
98.验证二叉搜索树
LeetCode链接 98. 验证二叉搜索树 - 力扣(LeetCode)
题目描述:
方法1:中序遍历+prev
package daimasuixiangshuati.day19_erchashu;
/**
* @Author LeiGe
* @Date 2023/12/6
* @Description todo
*/
public class YanZhengErChaSouSuoShu98_1 {
/**
* 方法1:中序遍历,如果是搜索二叉树,一定是不降序的
* 通过一个变量记录前一个子树的值prev
*
* @param root
* @return
*/
private long prev = Long.MIN_VALUE;
public boolean isValidBST(TreeNode root) {
//baseCase
if (root == null) {
return true;
}
//左子树
boolean left = isValidBST(root.left);
if (!left) {
return false;
}
//此节点
//此节点的值小于左子树节点的值
if (root.val <= prev) {
return false;
}
prev = root.val;
//右子树
boolean right = isValidBST(root.right);
return right;
}
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode() {
}
TreeNode(int val) {
this.val = val;
}
TreeNode(int val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}
}
方法2:中序遍历+数组
package daimasuixiangshuati.day19_erchashu;
import java.util.ArrayList;
/**
* @Author LeiGe
* @Date 2023/12/6
* @Description todo
*/
public class YanZhengErChaSouSuoShu98_2 {
/**
* 方法2:中序遍历,如果是搜索二叉树,一定是不降序的
* 1.将中序遍历的结果加入数组中
* 2.遍历数组是否是不降序的
*
* @param root
* @return
*/
public boolean isValidBST(TreeNode root) {
integers.clear();
traversal2(root);
for (int i = 1; i < integers.size(); i++) {
if (integers.get(i) <= integers.get(i - 1)) {
return false;
}
}
return true;
}
/**
* 中序遍历
*
* @param root
*/
ArrayList<Integer> integers = new ArrayList<>();
private void traversal2(TreeNode root) {
if (root == null) {
return;
}
traversal2(root.left);
integers.add(root.val);
traversal2(root.right);
}
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode() {
}
TreeNode(int val) {
this.val = val;
}
TreeNode(int val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}
}