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

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

给定一个二叉搜索树(Binary Search Tree),把它转换成为累加树(Greater Tree),使得每个节点的值是原来的节点值加上所有大于它的节点值之和。

例如:

输入: 原始二叉搜索树:
5
/
2 13

输出: 转换为累加树:
18
/
20 13

二叉搜索树:
1.如果root有左孩子,那么他的左孩子都比都比他小

2.如果root有右孩子,那么他的右孩子都比都比他大

3.root的孩子也具有以上性质

二叉搜索树的性质告诉我们:中序遍历得到的数组是有序的

解法一:

反向中序遍历:

先来看普通的中序遍历

if(root){
	traversal(root->left);
    //visit val and do some operation;
    cout << root->val;
    tracersal(root->right);
}

那么反向中序遍历就将顺序倒过来

if(root){
	traversal(root->right);
    //visit val and do some operation;
    cout << root->val;
    tracersal(root->left);
}

代码:

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

解法二:

Morris Traversal

算法描述:
一:cur有左孩子,找到左孩子的最右节点 记作mostRgight
Ⅰ:如果mostRgight->right == NULL,则mostRgight->right = cur, cur=cur->left;

​ Ⅱ:如果mostRgight->right != NULL,则mostRgight->rihgt = null,cur=cur->right;

二:如果cur无左孩子,访问该节点,cur=cur->rightl;

这实际上是一个搭桥和拆桥的过程,在纸上画出路径和mostright的指向就可以直观的看出来

比如 就{2,1,3}这棵二叉搜索树举例,cur==root时,mostright会指向1所在的节点,然后搭桥,mostRgight->right = cur,然后cur向左遍历cur=cur-left,cur遍历至1所在节点的时候,拆桥mostRgight->rihgt = null,然后向右边遍历cur=cur->right;

如果cur没有左孩子,那么cur过桥,cur = cur->right;

while(root){
	if(root->left != NULL){	
		TreeNode* temp = root->left;
        //找到mostright
        while(temp->right != NULL && temp->right != root) temp = temp->right;
    	//因为这里有两个限制条件,因此需要分类讨论
        if(temp->right == NULL){
            //搭桥
			temp->right = root;
            root = root->left;
        }
        else{
            //拆桥
			temp->right = NULL;
            root = root->right;
        }
    }
    else{
        //过桥
		root = root->right;
    }
}

回到这题,我们需要反向中序遍历,那么把left和right交换一下就好了

代码:

class Solution
{
public:
    int sum = 0;
    void MorisTraversal(TreeNode *root)
    {
        while (root)
        {
            if (root->right != NULL)
            {
                TreeNode *temp = root->right;
                //temp:右子树最左节点
                while (temp->left != NULL && temp->left != root)
                {
                    temp = temp->left;
                }
                //two situation
                if (temp->left == NULL)
                {
                    //first visit
                    temp->left = root; //construct the bridge
                    root = root->right;
                }
                else
                {
                    //at the monment  temp->right = root
                    //second visit and do some operation
                   	//deconstruct the bridge
                    temp->left = NULL;
                    cout << root->val << " ";
                    sum += root->val;
                    root->val = sum;
                    root = root->left;
                }
            }
            else
            {
                //visit val;
                cout << root->val << " ";
                sum += root->val;
                root->val = sum;
                root = root->left;
            }
        }
    }

    TreeNode *convertBST(TreeNode *root)
    {
        // if(root){
        //     convertBST(root->right);
        //     sum += root->val;
        //     root->val = sum;
        //     convertBST(root->left);
        // }
        MorisTraversal(root);
        return root;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值