算法训练营day22 | {669.修剪二叉搜索树, 108.将有序数组转换为二叉搜索树, 538. 把二叉搜索树转换为累加树}
第六章二叉树part08,二叉搜索树的修改和改造。
669. 修剪二叉搜索树
- 题目链接:669. 修剪二叉搜索树
- 文档讲解:代码随想录–669. 修剪二叉搜索树
- 视频讲解:你修剪的方式不对,我来给你纠正一下!| LeetCode:669. 修剪二叉搜索树
- 状态:和上题不同的是可能需要删除不止一个节点,判断遍历到的每个节点是否在区间内。
1.1 解题分析
本题的重点也在讨论节点的终止条件上,不过和上一题不同,需要完整遍历一整个树,不能遇到要删除的节点就返回。相反,要利用二叉搜索树的价值,能在当前节点就判断整棵子树的命运,实现剪枝。
分析递归三步曲:
- 参数和返回值是什么? 形参就是父递归给子递归的约束,然后返回修剪后的树的根节点。
- 确定递归的终止条件。 如果当前遍历到了根节点,则返回null;如果遇到要删除的节点,继续递归判断可能符合区间条件的子树。
- 确定单层递归的逻辑。 前序遍历,中左右,其实没有中的处理逻辑,重点在终止条件的处理上。
前序遍历-递归法
▶669. 修剪二叉搜索树1
2
3
4
5
6
7
8
9
10class Solution {
public TreeNode trimBST(TreeNode root, int low, int high) {
if (root == null) return null;
if (root.val < low) return trimBST(root.right, low, high);
if (root.val > high) return trimBST(root.left, low, high);
root.left = trimBST(root.left, low, high);
root.right = trimBST(root.right, low, high);
return root;
}
}
108. 将有序数组转换为二叉搜索树
- 题目链接:108.将有序数组转换为二叉搜索树
- 文档讲解:代码随想录–108.将有序数组转换为二叉搜索树
- 状态:构造一个BST,必须先构造根节点,适合采用前序遍历的方式。
2.1 解题分析
数组的区间下标左闭右闭。
分析递归三步曲:
- 参数和返回值是什么? 需要传入一个升序的整数数组,构造树的数组起始下标,终止下标,返回一个TreeNode;
- 确定递归的终止条件。 当数组起始下标 > 终止下标时,返回null。
- 确定单层递归的逻辑。 前序遍历,中左右,当前数组的长度/2 即为根节点元素所在位置,以此为分割线,划分左子树区间和右子树区间。
前序遍历-递归法
▶108. 将有序数组转换为二叉搜索树1
2
3
4
5
6
7
8
9
10
11
12
13
14class Solution {
public TreeNode sortedArrayToBST(int[] nums) {
return buildBST(nums, 0, nums.length - 1);
}
public TreeNode buildBST(int[] nums, int left, int right) {
if (left > right) return null;
int rootIndex = left + (right - left) / 2;
TreeNode root = new TreeNode(nums[rootIndex]);
root.left = buildBST(nums, left, rootIndex - 1);
root.right = buildBST(nums, rootIndex + 1, right);
return root;
}
}
538. 把二叉搜索树转换为累加树
- 题目链接:538. 把二叉搜索树转换为累加树
- 文档讲解:代码随想录–538. 把二叉搜索树转换为累加树
- 状态:想象二叉搜索树 中序遍历之后是一个有序递增数组,这题就简单了。
3.1 解题分析
暴力的方法是先遍历一遍获取一个树的totalSum,接着再中序遍历一遍,本轮的cuSum重新开始累加,然后遍历到哪个节点,就更新它的值为(totalSum - curSum)。
能不能只遍历一遍呢?那必须从后往前遍历,也就是右中左,并且反中序遍历这个二叉树,然后顺序累加即可。
分析递归三步曲:
- 参数和返回值是什么? 形参需要传入一个根节点,无需返回值,此外需要定义一个全局变量整数型pre,用于记录前一个结点的值。
- 确定递归的终止条件。 如果当前遍历到空节点,则返回null。
- 确定单层递归的逻辑。 反中序遍历,右中左,中:如果pre没有被赋值,给pre赋值,否则给pre加上当前值,然后更新当前节点的值。
反中序遍历-递归法
▶538. 把二叉搜索树转换为累加树1
2
3
4
5
6
7
8
9
10
11
12
13
14
15class Solution {
int pre = 0;
public TreeNode convertBST(TreeNode root) {
reverseInOrder(root);
return root;
}
public void reverseInOrder(TreeNode node) {
if (node == null) return;
reverseInOrder(node.right);
pre += node.val;
node.val = pre;
reverseInOrder(node.left);
}
}
4. 二叉树章节总结
33道题目,包含普通二叉树、二叉搜索树,可以看看打卡的博客回顾一下这8天做过的题目。
- 什么样的题目适合什么遍历方式?
- 递归三步曲如何分析?
- 递归函数什么时候需要返回值,什么时候不需要?
- 递归函数什么需要回溯,什么时候不需要?
- 递归函数什么时候需要定义全局变量,什么时候不需要?
涉及构造一个二叉树,无论是普通的二叉树还是二叉搜索树,一定是前序遍历,先构造根节点。
求普通二叉树的属性,一般是后序遍历,一般要通过递归函数的返回值做计算。
求二叉搜索树的属性,一定是中序遍历,不然浪费有序的特性。
学习时长:2小时
算法训练营day22 | {669.修剪二叉搜索树, 108.将有序数组转换为二叉搜索树, 538. 把二叉搜索树转换为累加树}
http://paopaotangzu.xyz/cn/day22_leetcode/