LeetCode538.把二叉搜索树转换为累加树

186 阅读2分钟

「这是我参与11月更文挑战的第15天,活动详情查看:2021最后一次更文挑战

把二叉搜索树转换为累加树

题目

给出二叉 搜索 树的根节点,该树的节点值各不相同,请你将其转换为累加树(Greater Sum Tree),使每个节点 node 的新值等于原树中大于或等于 node.val 的值之和。

提醒一下,二叉搜索树满足下列约束条件:

  • 节点的左子树仅包含键 小于 节点键的节点。
  • 节点的右子树仅包含键 大于 节点键的节点。
  • 左右子树也必须是二叉搜索树。

image.png

  • 输入:[4,1,6,0,2,5,7,null,null,null,3,null,null,null,8]

  • 输出:[30,36,21,36,35,26,15,null,null,null,33,null,null,null,8] 示例 2:

  • 输入:root = [0,null,1]

  • 输出:[1,null,1]

示例 3:

  • 输入:root = [1,0,2]
  • 输出:[3,3,2]

示例 4:

  • 输入:root = [3,2,4,1]
  • 输出:[7,9,4,10]

解法

首先,我们都知道二叉搜索树有个十分重要的特征就是有序,对二叉搜索树进行中序遍历得到的是一段从小到大的序列。而这道题目中累加树是按照右中左的顺序累加,这个顺序刚好和树的中序遍历相反,所以我们可以考虑对二叉搜索树做一个反中序遍历,然后做val值累加操作,这样就可以得到一颗累加树了

递归三要素

  • 递归的终止条件:遍历的节点为空,此层递归终止
  • 递归的参数及返回值:遍历的树的根节点,无需返回值
  • 递归的单层逻辑:如果右子树不为空遍历右子树,然后更新val值,并设置preval为自身val,供下一个遍历节点使用,如果左子树不为空遍历右子树
var convertBST = function(root) {
    // 保存上一个节点的值,初始值为0
    let preVal = 0
    // 这里是反中序遍历,右中左
    const travelNode = function(node){
        // 递归终止条件,节点不存在则返回
        if(!node) return;
        // 存在右子树则遍历右子树
        node.right && travelNode(node.right);
        // 更新节点值
        node.val += preVal;
        // 更新pre
        preVal = node.val;
        // 存在左子树则遍历左子树
        node.left && travelNode(node.left);
    }
    // 从根节点开始遍历树
    travelNode(root);
    return root;
};