题目难度 Medium
给出二叉搜索树的根节点,该二叉树的节点值各不相同,修改二叉树,使每个节点 node 的新值等于原树中大于或等于 node.val 的值之和。
提醒一下,二叉搜索树满足下列约束条件:
节点的左子树仅包含键小于节点键的节点。
节点的右子树仅包含键大于节点键的节点。
左右子树也必须是二叉搜索树。
示例:
输入:[4,1,6,0,2,5,7,null,null,null,3,null,null,null,8]
输出:[30,36,21,36,35,26,15,null,null,null,33,null,null,null,8]
提示:
树中的节点数介于 1 和 100 之间。
每个节点的值介于 0 和 100 之间。
给定的树为二叉搜索树。
这道题想到了之前做过的类似的一个题目,也是修改树的内容。考虑到它修改的顺序是 后-中-先。直观上看没有一种遍历方式是这个顺序的,但是恰好与先序遍历的顺序相反,所以我们的做法是:
先进行先序遍历,用一个数组存储所有的结点。然后在数组中从后到前依次相加,直接改变数组中的节点的值,进行改变。注意数组中存储的是指针,所以改变数组就可以改变原来的树。
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
void InOrderTraverse(TreeNode* T, vector &nums){
if (T){
InOrderTraverse(T->left,nums);
nums.push_back(T);
InOrderTraverse(T->right,nums);
}
}
TreeNode* bstToGst(TreeNode* root) {
vector nums;
InOrderTraverse(root,nums);
int temp=0;
for(int i=nums.size()-1;i>=0;i--){
if(nums[i]==NULL)
continue;
nums[i]->val+=temp;
temp=nums[i]->val;
}
return root;
}
};
但实际上还是考虑复杂了,我们只需构建一种后-中-先遍历的方法,用一个整型的全局变量储存前面的和即可。
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
int cur;
TreeNode* bstToGst(TreeNode* root) {
cur = 0;
dfs(root);
return root;
}
void dfs(TreeNode* x) {
if (x->right) dfs(x->right);
cur += x->val;
x->val = cur;
if (x->left) dfs(x->left);
}
};