算法笔记-转换二叉搜索树为累加树

124 阅读1分钟

需要充分利用二叉搜索树的有序特性: 右子树节点均大于根节点的值。

image.png

大致思路

找规律发现:

1.根节点是自身 + 左侧节点累计值

2.右子树节点是自身+自身的右子树

3.右子树的左节点是自身+父节点

所以代码随想录的解释最好理解:

二叉搜索树是有序的,从左到右、从小到大,那么如果他们是有序数组,节点值就是自身+自身后序节点的累加。

转换二叉搜索树为有序数组,不如控制遍历顺序由大到小,这样底部计算的值就已经累加好了。

可得 node->val += preResult; 那么结合二叉搜索树的特性(右子树 > 节点 > 左子树),由大到小的遍历顺序自然是先遍历右子树的最右节点:


/** 遍历左侧无法传递根节点的累加值进去 
    preResult = build(root->right);
    root->val += preResult;
    build(root->left); 
*/
// 改为全局变量
build(root->right);
gPrebuildResult += root->val;
root->val = gPrebuildResult;
build(root->left);

总结

  1. 修改节点的值,又要累加大于自身的值,那么必然是遍历到树的底部开始构建(中序、后序) 2.右子树节点值为自身 + 右子树累加上来的值(这时还不处理左子树就需要修改节点的值,必然中序先右遍历)

完整代码

class Solution {
public:
    int accOfRMLOrder = 0;
public:
    void travelByRML(TreeNode* root) {
        if (root == nullptr) { return; }
        travelByRML(root->right);
        root->val += accOfRMLOrder;
        accOfRMLOrder = root->val;
        travelByRML(root->left);
    }
    TreeNode* convertBST(TreeNode* root) {
        accOfRMLOrder = 0;
        travelByRML(root);
        return root;
    }
};