摘要
本文介绍LeetCode中的三道二叉树题目:669.修剪二叉搜索树、108.将有序数组转为二叉搜索树、538.把二叉搜索树转为累加树。最后,由ChatGPT总结了二叉树问题的关键解题技巧。
1、669. 修剪二叉搜索树
1.1 思路
- 递归遍历,利用二叉搜索树是有序的
- 如果要删除的元素小于low,返回修剪后的右子树;如果要删除的元素大于high,返回修剪后的左子树
- 递归地对其左子树和右子树进行修剪
ChatGPT的思路
- 对于BST,其左子树中的所有节点值都小于根节点的值,而右子树中的所有节点值都大于根节点的值。
- 因此,如果当前节点的值小于
low,那么它以及其左子树的所有节点都应该被修剪,因为它们都小于low。 - 同样,如果当前节点的值大于
high,那么它以及其右子树的所有节点都应该被修剪,因为它们都大于high。 - 如果当前节点的值在
[low, high]的范围内,那么我们保留该节点,然后递归地对其左子树和右子树进行修剪。
1.2 代码
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;
}
2、108.将有序数组转换为二叉搜索树
2.1 思路
- 递归遍历,定义start, end分别为开始下标和结束下标
- 递归终止:start<end返回空,start==end返回
new TreeNode(nums[start]) - 递归过程:定义mid=(start+end)/2,左子树等于[start, mid-1],右子树等于[mid+1, end]
ChatGPT的思路
- 对于BST,它的中序遍历是一个升序排列的数组。因此,如果我们想要构建一个高度平衡的BST,可以选择中间元素作为根节点,然后将左侧的部分数组构建成左子树,右侧的部分数组构建成右子树。
- 为了确保树的高度平衡,我们需要不断地选择中间元素作为根节点,并递归构建左右子树,直到所有的元素都被使用。
- 递归函数的输入参数可以包括数组的起始索引和结束索引,表示当前子数组的范围。递归的终止条件是起始索引大于结束索引,此时返回
null表示空树。 - 在每一次递归调用中,我们计算中间元素的索引,选择它作为当前子树的根节点,并将左侧部分数组和右侧部分数组传递给递归函数,分别构建左子树和右子树。
- 最后,将当前根节点返回,构建完成的BST就是由递归函数返回的根节点及其子树构成的。
2.2 代码
public TreeNode sortedArrayToBST(int[] nums) {
return doSortedArrayToBST(nums, 0, nums.length-1);
}
public TreeNode doSortedArrayToBST(int[] nums, int start, int end) {
if(start > end) {
return null;
}
if(start == end) {
return new TreeNode(nums[start]);
}
int mid = (start + end) / 2;
TreeNode node = new TreeNode(nums[mid]);
node.left = doSortedArrayToBST(nums, start, mid-1);
node.right = doSortedArrayToBST(nums, mid+1, end);
return node;
}
3、538.把二叉搜索树转换为累加树
3.1 思路
- 同501.二叉搜索树中的众数,中序遍历为左右中,因为需要从大到小遍历, 所以遍历顺序是右中左
- 递归终止:当前节点为null
- 递归过程:定义prev为前一个节点,设置root节点的值为当前值+前一个节点的值,然后重新设置prev=root
3.2 代码
public TreeNode convertBST(TreeNode root) {
doConvertBST(root);
return root;
}
public void doConvertBST(TreeNode root) {
if(root == null) {
return;
}
doConvertBST(root.right);
root.val = root.val + prev.val;
prev = root;
doConvertBST(root.left);
}
4、总结
这篇总结提供了对「代码随想录」中关于二叉树的文章的分类和摘要,以及每个问题的递归和迭代解决方案。以下是主要内容的概要:
- 二叉树的理论基础:介绍了二叉树的基本概念,包括种类、存储方式、遍历方式和定义方式。
- 二叉树的遍历方式:详细讨论了深度优先遍历和广度优先遍历的递归和迭代方法。
- 求二叉树的属性:解释了如何计算二叉树的最大深度、最小深度、节点数量、是否平衡、路径总和等属性,并提供了递归和迭代的解决方案。
- 二叉树的修改与构造:包括翻转二叉树、构造二叉树、构造最大的二叉树、合并两个二叉树等问题的递归和迭代方法。
- 求二叉搜索树的属性:涵盖了二叉搜索树中的搜索、判断是否为二叉搜索树、找最小绝对差、求众数、二叉搜索树转累加树等问题的解决方案。
- 二叉树的公共祖先问题:解释了在二叉树中找到两个节点的最近公共祖先的递归和迭代方法。
- 二叉搜索树的修改与构造:包括在二叉搜索树中插入节点、删除节点、修剪树、构造二叉搜索树等问题的解决方案。
总之,这篇总结提供了对二叉树相关问题的系统分类和解决方法,有助于学习和复习与二叉树相关的算法和数据结构知识。
1、二叉树题目选择什么遍历顺序?
涉及到二叉树的构造,无论普通二叉树还是二叉搜索树一定前序,都是先构造中节点。
求普通二叉树的属性,一般是后序,一般要通过递归函数的返回值做计算。
求二叉搜索树的属性,一定是中序了,要不白瞎了有序性了。