1 题目描述
给定一个二叉搜索树(Binary Search Tree),把它转换成为累加树(Greater Tree),使得每个节点的值是原来的节点值加上所有大于它的节点值之和。
2 实例
3 思路
- 先实现根节点的累加,遍历所有节点。
- 在实现左右子节点的累加遍历
4 遇上的问题
- 遍历?先序后序中序,要哪个遍历好,最后选择了中序。
- 题目累加的要求大于等于原节点值,那就要比较,如果要比较那就要传值。(做完看官方题解才发现,原来给的二叉树是排好序的!!!)所以又重载了原方法,导致 代码量又加大了。真是莫得常识的笨猫。
- 累加的树,emm,但是第一次改的时候发现,我遍历第一个节点值,累加完发现树被修改了,对后面的遍历产生了影响!我又建了一个新树(笨猫)
5 结果
6 反思
- 二叉搜索树,是一个左节点小于父节点,右节点大于父节点的树!
- 时间耗费太多了,全部遍历太浪费了,毕竟左右节点已经大小区分好了。可以只遍历右节点和父节点的,然后累加起来。
- 思维不够清晰,需要再狂练啊!
- 又是可读性极差,长得像裹脚布的又不好读。需要再注意!
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
//全局变量copyTree,用于保存累加后的值。
TreeNode copyTree ;
//给定的方法结构,后来被我重载了
public TreeNode convertBST(TreeNode root) {
//如果null对象进来就直接返回
if(root == null){
return null;
}
//给copyTree创建和给定的树值一样的父节点
copyTree = new TreeNode(root.val);
//把给的树和copyTree树传过去给重载方法
convertBST(root,root,copyTree);
return copyTree;
}
//中序遍历,每次从头开始
public void convertBST(TreeNode node,TreeNode root,TreeNode copyTree) {
//遍历值和创建对应累加树节点的方法
equalsVal(root,node.val,copyTree);
//对左节点进行递归遍历
if(node.left!=null){
copyTree.left = new TreeNode(node.left.val);
convertBST(node.left,root,copyTree.left);
}
//对右节点进行递归遍历
if(node.right!=null){
copyTree.right = new TreeNode(node.right.val);
convertBST(node.right,root,copyTree.right);
}
}
//遍历值和创建对应累加树节点的方法
//root 根节点,每次遍历的开头
//target 目标节点的值,要和其他节点比较大小的节点的节点值
//copyTree 用于保存累加树节点
public int equalsVal(TreeNode root,int target,TreeNode copyTree){
int value = 0;
//节点存在,节点值大于目标节点,并且累加过程中要包含自己的值
if(root!=null&& root.val >= target){
value += root.val;
}
//左子树不为空,左子树进行递归
if(root.left != null){
value += equalsVal(root.left,target,copyTree);
}
//右子树不为空,右子树进行递归
if(root.right != null){
value += equalsVal(root.right,target,copyTree);
}
//将值赋给了copyTree
copyTree.val = value;
//在比较过程中,如果对该节点的值比目标节点大的话,返回比较的结果
if(root.val >= target){
return value;
}else{
return value;
}
}
}
7 学习官方的算法
class Solution {
int sum = 0;
public TreeNode convertBST(TreeNode root) {
if (root != null) {
convertBST(root.right);
sum += root.val;
root.val = sum;
convertBST(root.left);
}
return root;
}
}
/*
作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/convert-bst-to-greater-tree/solution/ba-er-cha-sou-suo-shu-zhuan-huan-wei-lei-jia-sh-14/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
*/
在这个算法里,巧妙的运用了二叉搜索树左子树必然小于根节点,右子树必然大于根节点,树的最深最右节点开始累加,遍历右、中、左,并且累加赋值,只需要遍历一遍树,一边遍历一边赋值,也就是O(n),就可以直接得到一颗累加树。
但是也存在问题,这个算法里默认没有相同值,如果有相同的两个数,就会出现问题,因为在累加中并不存在判断,所以一旦有相同的值也照样会累加,但是题目要求的是自身和大于自身的所有值,所以会出现问题。
我搜了搜BST,发现BST是二叉搜索树,在这个二叉搜索树中结构里用次数表示相同的数,有相同则index加1,然而官方在注释中给的树结构并没有一个int类型的index应该是默认不考虑相等情况。
8 收获
- BST,二叉搜索树(二次排序树、二次查找树),根节点必定大于左子树,必定小于右子树,左子树和右子树也依然是二次搜索树。
- 写算法时利用树的特性会使得算法设计更为简单!。
题目来源:力扣(LeetCode)
相关链接
题目著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。