leetcode题解538:把二叉搜索树转换为累加树
一、题目内容
题目要求将给定的二叉搜索树(BST)转换为累加树(Greater Sum Tree),使每个节点的值等于原树中大于或等于该节点值的所有节点值之和。转换后的树应保持原有的二叉搜索树结构。
二、题目分析
(一)输入和输出
输入:二叉搜索树的根节点 root
。
输出:转换后的累加树的根节点。
(二)递归函数 convertBST
的逻辑
基本情况:如果当前节点为空(root == NULL
),说明当前分支没有节点,直接返回 NULL
。
递归逻辑:
-
从右子树开始递归处理,因为右子树的值大于当前节点的值。
-
更新当前节点的值为当前节点值加上之前遍历到的节点值之和(通过一个全局变量
pre
记录)。 -
更新全局变量
pre
为当前节点的新值。 -
递归地对左子树进行处理。
三、解题要点
(一)二叉搜索树的定义
二叉搜索树是一种特殊的二叉树,其性质是:对于任意节点,其左子树上所有节点的值都小于该节点的值,其右子树上所有节点的值都大于该节点的值。这一性质是转换操作的基础,转换操作需要保持这一性质不变。
(二)转换操作的性质
转换操作需要保持二叉搜索树的结构不变,同时更新每个节点的值为原树中大于或等于该节点值的所有节点值之和。
(三)解题思路
基本情况:
如果当前为空节点(root == NULL
),直接返回 NULL
。这是递归的终止条件。
递归逻辑:
-
从右子树开始递归处理,因为右子树的值大于当前节点的值。
-
更新当前节点的值为当前节点值加上之前遍历到的节点值之和。
-
更新全局变量
pre
为当前节点的新值。 -
递归地对左子树进行处理。
递归返回:
递归返回时,返回当前节点。这一步确保了递归调用的正确性,使得每次递归返回后,当前节点的状态被正确恢复,不会影响后续的递归调用。
四、代码解答
class Solution {
public:int pre = 0; // 用于记录之前遍历到的节点值之和TreeNode* convertBST(TreeNode* root) {// 如果当前节点为空,直接返回 NULLif (root == NULL) return NULL;// 递归地对右子树进行处理convertBST(root->right);// 更新当前节点的值root->val += pre;pre = root->val; // 更新全局变量 pre// 递归地对左子树进行处理convertBST(root->left);// 返回当前节点return root;}
};
五、详细注释
(一)递归函数 convertBST
基本情况:如果当前节点为空,直接返回 NULL
。
递归逻辑:根据二叉搜索树的性质,从右子树开始递归,更新当前节点的值,然后递归处理左子树。
返回值:返回当前节点,确保递归调用后,当前节点的状态被正确恢复。
(二)全局变量 pre
全局变量 pre
用于记录之前遍历到的节点值之和。它在递归过程中被不断更新,用于计算当前节点的新值。
六、递归和回溯的详细解释
(一)递归
递归是一种函数调用自身的方法,用于解决复杂问题。在本题中,递归用于逐层遍历每个节点,根据二叉搜索树的性质,从右子树开始遍历,更新当前节点的值,并对左子树进行处理。递归的核心思想是将问题分解为更小的子问题,通过解决子问题来解决原问题。
(二)终止条件
递归的终止条件是当前节点为空,此时直接返回 NULL
。这是递归的出口,确保递归不会无限进行下去。
(三)回溯
在递归调用返回后,通过返回值恢复到当前节点的状态,确保每次递归返回后,状态正确,不会影响后续的递归调用。
(四)递归调用的详细过程
假设我们有一个二叉搜索树,根节点为 root
,值为 5
,其左子节点值为 3
,右子节点值为 7
。现在要将其转换为累加树。
-
初始调用:
convertBST(root)
,当前节点值为5
。 -
递归调用右子树:
convertBST(root->right)
,当前节点值为7
,更新pre
为7
。 -
递归调用左子树:
convertBST(root->left)
,当前节点值为3
,更新pre
为10
(7 + 3
)。 -
最终返回转换后的根节点,其值为
12
,左子树的值为10
,右子树的值为7
。
(五)代码执行过程示例
假设我们有一个二叉搜索树,根节点为 root
,值为 5
,其左子节点值为 3
,右子节点值为 7
。现在要将其转换为累加树。
-
初始调用:
convertBST(root)
,当前节点值为5
。 -
递归调用右子树:
convertBST(root->right)
,当前节点值为7
,更新pre
为7
。 -
递归调用左子树:
convertBST(root->left)
,当前节点值为3
,更新pre
为10
(7 + 3
)。 -
最终返回转换后的根节点,其值为
12
,左子树的值为10
,右子树的值为7
。
通过以上分析和代码实现,我们可以高效地完成二叉搜索树的转换操作,同时保持树的结构和性质不变。