0%

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

1. 中序遍历

BST的中序遍历得到的结果是从小到大的有序序列,可以使用一个数组记录这个序列,然后遍历BST,对每个节点累加值。
为了降低累加过程需要的时间,可以使用hash表统计大于各个值的节点值之和,从而避免每次都要重新求和。
时间O(n),空间O(n)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
class Solution {
public:
TreeNode* convertBST(TreeNode* root) {
if (root == nullptr)
return root;

vector<int> vals;
midOrder(root, vals);
unordered_map<int, int> sum;
int temp = 0;
for (int i = vals.size() - 1; i >= 0; i--) {
temp += vals[i];
sum[vals[i]] = temp;
}

queue<TreeNode*> q;
q.push(root);
TreeNode* cur;
while (!q.empty()) {
cur = q.front();
q.pop();
cur->val = sum[cur->val];
if (cur->left != nullptr)
q.push(cur->left);
if (cur->right != nullptr)
q.push(cur->right);
}

return root;
}
private:
void midOrder(TreeNode* root, vector<int>& vals) {
stack<TreeNode*> st;
while (root != nullptr || !st.empty()) {
if (root == nullptr) {
root = st.top();
st.pop();
vals.push_back(root->val);
root = root->right;
} else {
st.push(root);
root = root->left;
}
}
}
};

2. 反向中序遍历

要修改一个节点需要获取比这个节点大的值,比它大的值在它的右子树中,同时还来自于它的各层父节点(如果它是父节点的左孩子的话)。
如果按照这个思路求解每个节点的比它大的所有值是有些困难的,但是联想到中序遍历得到的有序序列就会比较简单。
中序左根右遍历BST得到的是由小到大的有序序列,因此反向中序右根左遍历BST得到的是由大到小的有序序列。
题目需要的比每个节点大的值正好由反向中序遍历提供了。
时间O(n),空间O(n)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Solution {
public:
TreeNode* convertBST(TreeNode* root) {
TreeNode* keepRoot = root;
stack<TreeNode*> st;
int sum = 0;
while (root != nullptr || !st.empty()) {
if (root == nullptr) {
root = st.top();
st.pop();
sum += root->val;
root->val = sum;
root = root->left;
} else {
st.push(root);
root = root->right;
}
}

return keepRoot;
}
};