part9
day22-1 ● 669. 修剪二叉搜索树
解题思路
删除的操作:通过当前层往上一层返回值然后上一层其对应的孩子来接住返回值最终达到删除的效果
常见误区及代码
为啥不直接返回right而返回递归后的right?是因为右子树不完全都满足条件
class Solution {
public TreeNode trimBST(TreeNode root, int low, int high) {
if(root == null){
return null;
}
if(root.val < low || roo.val > high){
return null;
}
root.left = trimBST(root.left, low, high);
root.right = trimBST(root.right, low, high);
return root;
}
}
正确代码
/**
* Definition for a binary tree node.
* 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;
* }
* }
*/
// 递归法
class Solution {
public TreeNode trimBST(TreeNode root, int low, int high) {
if(root == null){
return null;
}
if(root.val < low){
// 为啥不直接返回right而返回递归后的right?是因为右子树不完全都满足条件区间的条件限制
// 为啥不递归去找左子树,因为是一棵二叉搜索树,有左小右大的特点
TreeNode right = trimBST(root.right, low, high);
return right;
}
// 如果root(当前节点)的元素大于high的,那么应该递归左子树(右子树肯定更大,所以不用管了),并返回左子树符合条件的头结点。
if(root.val > high){
TreeNode left = trimBST(root.left, low, high);
return left;
}
root.left = trimBST(root.left, low, high);
root.right = trimBST(root.right, low, high);
return root;
}
}
总结
二叉树移除节点的过程是通过当前层往上一层返回值然后上一层其对应的孩子来接住返回值最终达到删除的效果
删除节点的子树中可能还有符合区间的节点,所以还需要继续往下进行递归
day22-2 ● 108.将有序数组转换为二叉搜索树
题意
- 二叉搜索数应该是平衡的否则可以构造成链表
- 中序后序构造二叉树和构造最大二叉树的思路是:选取中间节点,将数组分为左区间和右区间,递归遍历左区间去构成左子树,递归遍历右区间去构成右子树
解题思路
- 选中间节点,保证左右区间的节点数量相同或者相差一个,目的是为了保证构造的二叉树平衡
- 数组是有按照升序排序的有序数组
代码实现
/**
* Definition for a binary tree node.
* 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;
* }
* }
*/
class Solution {
// 递归法:左闭右闭
public TreeNode sortedArrayToBST(int[] nums) {
return traversal(nums, 0, nums.length - 1);
}
private TreeNode traversal(int[] nums, int left, int right){
if(left > right){// 不为取等是因为只用一个元素的时候也要构造二叉树的节点
return null;
}
int mid = left + (right - left)/2;
TreeNode root = new TreeNode(nums[mid]);
// 构造左子树
root.left = traversal(nums, left, mid -1);
// 构造右子树
root.right = traversal(nums, mid + 1, right);
return root;
}
// 递归法:左闭右开
public TreeNode sortedArrayToBST(int[] nums) {
return traversal(nums, 0, nums.length);
}
private TreeNode traversal(int[] nums, int left, int right){
if(left >= right){// 不为取等是因为只用一个元素的时候也要构造二叉树的节点
return null;
}
int mid = left + (right - left)/2;
TreeNode root = new TreeNode(nums[mid]);
// 构造左子树
root.left = traversal(nums, left, mid );
// 构造右子树
root.right = traversal(nums, mid + 1 , right);
return root;
}
}
总结
- 区间划分整体的一致性(循环不变量的重要性)
- 构造的二叉树不唯一
- 构造二叉树的思路不断中间分割,然后递归处理左区间,右区间,也可以说是分治
day22-3 ● 538.把二叉搜索树转换为累加树
解题思路
- 二叉搜索树中序遍历(左中右)得到的是从小到大的有序
- 累加的顺序是右中左,我们需要反中序遍历这个二叉树,然后顺序累加
代码实现
/**
* Definition for a binary tree node.
* 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;
* }
* }
*/
class Solution {
// 递归法发:反中序
int sum;
public TreeNode convertBST(TreeNode root) {
int sum = 0;
traversal(root);
return root;
}
// 按照右中左的顺序遍历,并进行累加
public void traversal(TreeNode root){
if(root == null){
return;
}
// 右
traversal(root.right);
// 中
sum += root.val;
root.val = sum;
// 左
traversal(root.left);
}
// 迭代法
public TreeNode convertBST(TreeNode root) {
int pre = 0;
Stack<TreeNode> stack = new Stack<>();
if(root == null){
return null;
}
stack.add(root);
while(!stack.isEmpty()){
TreeNode cur = stack.pop();
// cur != null的状况,只负责将node存到stack中
if(cur != null){
if(cur.left != null){ // 右
stack.add(cur.left);
}
stack.add(cur); // 中
stack.add(null);
if(cur.right != null){ // 左
stack.add(cur.right);
}
}else{
// cur == null的情况,负责做累加逻辑
TreeNode temp = stack.pop();
temp.val += pre;
pre = temp.val;
}
}
return root;
}
}
总结
day22-4 ● 总结篇
- 递归三部曲:返回值、参数、终止条件、单层逻辑
- 二叉树的遍历方式
- 深度优先遍历
- 前序遍历(递归法、迭代法)
- 中序遍历(递归法、迭代法)
- 后续遍历 (递归法、迭代法)
- 广度优先遍历
- 层次遍历(迭代法)
- 深度优先遍历
- 二叉树的属性
- 对称
- 最大深度
- 最小深度
- 求节点数
- 平衡
- 所有路径
- 递归中的回溯
- 左叶子之和
- 左下角的值
- 路径总和
- 二叉树的修改与改造
- 翻转
- 构造
- 最大二叉树
- 合并两个二叉树
- 二叉搜索数的属性
- 搜索
- 判断是否是二叉搜索树
- 最小绝对差
- 众数
- 转累加树
- 二叉数公共祖先问题
- 二叉树
- 二叉搜索树
- 二叉搜索树的修改与构造
- 插入
- 删除
- 修建
- 构造
- 大总结:TODO