需要充分利用二叉搜索树的有序特性: 右子树节点均大于根节点的值。
大致思路
找规律发现:
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);
总结
- 修改节点的值,又要累加大于自身的值,那么必然是遍历到树的底部开始构建(中序、后序) 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;
}
};