看到累加可能会有一点麻烦,但二叉搜索树是有序树,那么有序的元素如何求累加呢?
其实这就是⼀棵树,⼤家可能看起来有点别扭,换⼀个⻆度来看,这就是⼀个有序数组[2, 5, 13],求从后到前的累加数组,也就是[20, 18, 13],是不是感觉这就简单了。
为什么变成数组就是感觉简单了呢?
因为数组⼤家都知道怎么遍历啊,从后向前,挨个累加就完事了,这换成了⼆叉搜索树,看起来就别扭了⼀些。
那么知道如何遍历这个⼆叉树,也就迎刃⽽解了, 从树中可以看出累加的顺序是右中左,所以我们需要反中序遍历这个⼆叉树,然后顺序累加就可以了
递归法
1、递归函数参数以及返回值
这⾥很明确了,不需要递归函数的返回值做什么操作了,要遍历整棵树。
同时需要定义⼀个全局变量pre,⽤来保存cur节点的前⼀个节点的数值,定义为int型就可以了。
int pre; // 记录前⼀个节点的数值
void traversal(TreeNode* cur)
2、确定终⽌条件
if (cur == NULL) return;
3、确定单层递归的逻辑
注意要右中左来遍历⼆叉树, 中节点的处理逻辑就是让cur的数值加上前⼀个节点的数值。
traversal(cur->right);//右
cur->val=cur->val+pre;//中
pre=cur->val;
traversal(cur->left);//左
return;
整体递归代码
class Solution {
public:
int pre=0;
void traversal(TreeNode* cur){
if (cur == NULL) return;
traversal(cur->right);
cur->val=cur->val+pre;
pre=cur->val;
traversal(cur->left);
return;
}
TreeNode* convertBST(TreeNode* root) {
traversal(root);
return root;
}
};
迭代法1
class Solution{
public:
TreeNode* convertBST(TreeNode* root){
if(root==NULL) return root;
stack<TreeNode*> st;
int pre=0;
st.push(root);
while(!st.empty()){
TreeNode *node=st.top();
if(node!=nullptr) {
st.pop();
if(node->left) st.push(node->left);
st.push(node);
st.push(NULL);
if(node->right) st.push(node->right);
}else{
st.pop();
node=st.top();
st.pop();
node->val=node->val+pre;
pre=node->val;
}
}
return root;
}
};
迭代法2
class Solution{
public:
TreeNode* convertBST(TreeNode* root){
if(root==NULL) return root;
stack<TreeNode*> st;
TreeNode* cur=root;
int pre=0;
while(cur!=NULL||!st.empty()){
if(cur!=NULL){
st.push(cur);
cur=cur->right;
}else{
cur=st.top();
st.pop();
cur->val+=pre;
pre=cur->val;
cur=cur->left;
}
}
return root;
}
};
在⼆叉树题⽬选择什么遍历顺序是头疼的事情,我们做了这么多⼆叉树的题⽬了, 给⼤家⼤体分分类。
1、涉及到⼆叉树的构造,⽆论普通⼆叉树还是⼆叉搜索树⼀定前序,都是先构造中节点。
2、求普通⼆叉树的属性,⼀般是后序,⼀般要通过递归函数的返回值做计算。
3、求⼆叉搜索树的属性,⼀定是中序了,要不⽩瞎了有序性了。
注意在普通⼆叉树的属性中,我⽤的是⼀般为后序,例如单纯求深度就⽤前序, ⼆叉树:找所有路径也⽤了前序,
这是为了⽅便让⽗节点指向⼦节点。
所以求普通⼆叉树的属性还是要具体问题具体分析。
最后,⼆叉树系列就这么完美结束了接下来我们⼜要开始新的系列了「回溯算法」!