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

本文介绍了两种方法将二叉搜索树的节点值转换,使其每个节点的值等于从根节点到该节点路径上的所有节点值之和,同时探讨了如何通过Morris遍历降低空间复杂度。这两种方法分别是深度优先搜索(DFS)和Morris遍历,分别展示了它们在处理二叉搜索树时的效率和特点。
摘要由CSDN通过智能技术生成

在这里插入图片描述

1、深度遍历

考虑到我们使用的是二叉搜索树,右子树中的值总比左子树中的值大。因此我们可以按照“右根左”的顺序遍历每一个节点并将节点的和进行累加,而后将累加的值赋给每一个节点即可。

class Solution {
public:
    int dfs(TreeNode *root, int tempSum) {
        if (!root) return tempSum;
        tempSum = dfs(root->right, tempSum);
        tempSum = tempSum + root->val;
        root->val = tempSum;
        tempSum = dfs(root->left, tempSum);
        return tempSum;
    }

    TreeNode *convertBST(TreeNode *root) {
        dfs(root, 0);
        return root;
    }
};

class Solution {
public:
    int tempSum = 0;

    TreeNode *convertBST(TreeNode *root) {
        if (root != nullptr) {
            convertBST(root->right);
            tempSum += root->val;
            root->val = tempSum;
            convertBST(root->left);
        }
        return root;
    }
};

2、Morris 遍历

考虑到我们在对二叉树进行遍历时,无论是递归还是迭代都会占用O(n)的空间复杂度,因此我们可以使用Morris 遍历对二叉树的遍历进行优化,将空间复杂度降低到O(1)。

Morris 遍历之所以能降低空间复杂度在于其利用了未使用到的节点的空指针。由于本题中我们采用反序中序遍历进行搜索,我们可以这样进行Morris 遍历:1、当当前节点的右子节点为空时,说明当前节点是最右的节点,我们处理当前节点并遍历当前节点的左子节点;2、当当前节点的右子节点不为空时,我们找到当前节点右子树中的最左节点(显然该节点的左指针一定为空),此时我们将其左指针指向当前节点,这样我们就能够通过左指针直接抵达根节点而不需要通过栈来实现,而后我们继续遍历当前节点的右子节点。若此时最左节点的左指针不为空,说明此时当前的最左节点的左指针指向当前节点,此时我们先将最左节点的左指针置为空并对当前节点进行处理,而后将当前节点更新为当前节点的左子节点即通过指针回到当前节点对应的上一个根节点或左子树节点。

class Solution {
public:
    TreeNode* getSuccessor(TreeNode* node) {
        TreeNode* succ = node->right;
        while (succ->left != nullptr && succ->left != node) {
            succ = succ->left;
        }
        return succ;
    }

    TreeNode* convertBST(TreeNode* root) {
        int sum = 0;
        TreeNode* node = root;

        while (node != nullptr) {
            if (node->right == nullptr) {
                sum += node->val;
                node->val = sum;
                node = node->left;
            } else {
                TreeNode* succ = getSuccessor(node);
                if (succ->left == nullptr) {
                    succ->left = node;
                    node = node->right;
                } else {
                    succ->left = nullptr;
                    sum += node->val;
                    node->val = sum;
                    node = node->left;
                }
            }
        }

        return root;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值