本文共 2454 字,大约阅读时间需要 8 分钟。
Given a Binary Search Tree (BST), convert it to a Greater Tree such that every key of the original BST is changed to the original key plus sum of all keys greater than the original key in BST.
Example 1:
没有给出.
题目的意思是给出一个二分查找树,更改里面的节点值,使得更改后的节点值为原来的节点加上所有比它大的节点的值。比如例子中的节点5,因为只有节点13比它大,所以更改的值为5+13=18,而对于节点2,因为节点5和节点13都比它大,所以更改的值为2+5+13=20。
题目看起来似乎蛮复杂的,最笨的方法就是对于某一个节点得找出所有比它大的节点,然后把值相加。但是这其中有很多重复的工作,同时也没有利用好题目给出的是二分查找树这一条件。
二分查找树的特点是中序遍历的结果是一个升序序列。而我们做加法时最简单的顺序就是从最大的值开始,降序地做下去。在树中对应的就是最右的叶子节点开始,因为该节点是最大的。如果对二分查找树有一定的敏感度的话,应该很容易就发现一个性质:如果我们按照中序遍历的逆序,即先右子节点,再父节点,最后左子节点顺序遍历的话,刚好就能降序地访问每一个节点。比如例子中就会是以13,5,2的顺序访问,这样我们每访问一个节点,就记录下到该节点的和,并在访问下一节点时将该和值加到节点的值上。以例子说明:
初始sum为0。 访问到13,更新节点值为13+sum=13+0=13,sum更新为sum+13=0+13=13; 访问到5,更新节点值为5+sum=5+13=18,sum更新为sum+5=13+5=18; 访问到2,更新节点值为2+sum=2+18=20,sum更新为sum+2=18+2=20;因此,题目其实考的就是BST中序对应的逆序遍历,先访问右子树,然后父节点,最后左子树,并在访问过程中记录已访问的节点总和,累加到当前的节点上。见下面我的代码。
通过之后看了一下其他大神的解法,关键的地方就是逆中序遍历,不同的可能就是和值的处理,我上面的过程中就绕了一下,其中从我举的例子就能看到sum和更新的节点是一样,真正正确的理解应该是更新后的节点值是逆中序遍历中包含该节点的所有已访问节点的和值。下面参考代码就是体现这一点。
/** * 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 dfs(TreeNode *root, int &sum) { if (root->right) dfs(root->right, sum); int temp = root->val; root->val += sum; sum += temp; if (root->left) dfs(root->left, sum); } TreeNode* convertBST(TreeNode* root) { if (root) { int sum = 0; dfs(root, sum); } 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 {private: int cur_sum = 0;public: void travel(TreeNode* root){ if (!root) return; if (root->right) travel(root->right); root->val = (cur_sum += root->val); if (root->left) travel(root->left); } TreeNode* convertBST(TreeNode* root) { travel(root); return root; }};
这道题很不错,很高兴自己能够在大概10分钟左右做出来。以前关于BST,第一反应是中序结果为递增序列,通过做这道题,我自己想到了逆中序遍历的结果就是递减序列,一下子有种豁然开朗的感觉。对于常见的数据结构应该就要这样灵活运用,平时就得多做题多去思考,厚积薄发。
终于把进度赶回来,下一周加油!继续做其他课程的项目中,如果有时间会写写最近自己做的小项目,加油加油~