二叉搜索树c++_二叉树:搜索树转成累加树

041c56245b3a826a38af371d66c807e8.gif 给「代码随想录」一个星标吧!

先祝大家1024节日快乐!!

今天应该是一个程序猿普天同庆的日子,所以今天的题目比较简单,只要认真把前面每天的文章都看了,今天的题目就是分分钟的事了,毕竟程序猿何苦为难程序猿呢,大家都愉快过节!

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

题目链接:https://leetcode-cn.com/problems/convert-bst-to-greater-tree/

给出二叉 搜索 树的根节点,该树的节点值各不相同,请你将其转换为累加树(Greater Sum Tree),使每个节点 node 的新值等于原树中大于或等于 node.val 的值之和。

提醒一下,二叉搜索树满足下列约束条件:

节点的左子树仅包含键 小于 节点键的节点。节点的右子树仅包含键 大于 节点键的节点。左右子树也必须是二叉搜索树。

示例 1:

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

输入:[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]

示例 2:
输入:root = [0,null,1]
输出:[1,null,1]

示例 3:
输入:root = [1,0,2]
输出:[3,3,2]

示例 4:
输入:root = [3,2,4,1]
输出:[7,9,4,10]

提示:

  • 树中的节点数介于 0 和 104 之间。
  • 每个节点的值介于 -104 和 104 之间。
  • 树中的所有值 互不相同 。
  • 给定的树为二叉搜索树。

思路

一看到累加树,相信很多小伙伴都会疑惑:如何累加?遇到一个节点,然后在遍历其他节点累加?怎么一想这么麻烦呢。

然后再发现这是一颗二叉搜索树,二叉搜索树啊,这是有序的啊。

那么有序的元素如果求累加呢?

「其实这就是一棵树,大家可能看起来有点别扭,换一个角度来看,这就是一个有序数组[2, 5, 13],求从后到前的累加数组,也就是[20, 18, 13],是不是感觉这就简单了。」

为什么变成数组就是感觉简单了呢?

因为数组大家都知道怎么遍历啊,从后向前,挨个累加就完事了,这换成了二叉搜索树,看起来就别扭了一些是不是。

那么知道如何遍历这个二叉树,也就迎刃而解了,「从树中可以看出累加的顺序是右中左,所以我们需要反中序遍历这个二叉树,然后顺序累加就可以了」

递归

遍历顺序如图所示:

9c2c07dc83aec0737f51a78775c1646e.png

本题依然需要一个pre指针记录当前遍历节点cur的前一个节点,这样才方便做累加。

pre指针的使用技巧,我们在二叉树:搜索树的最小绝对差和二叉树:我的众数是多少?都提到了,这是常用的操作手段。

  • 递归函数参数以及返回值

这里很明确了,不需要递归函数的返回值做什么操作了,要遍历整棵树。

同时需要定义一个全局变量pre,用来保存cur节点的前一个节点的数值,定义为int型就可以了。

代码如下:

int pre; // 记录前一个节点的数值
void traversal(TreeNode* cur) 
  • 确定终止条件

遇空就终止。

if (cur == NULL) return;
  • 确定单层递归的逻辑

注意「要右中左来遍历二叉树」, 中节点的处理逻辑就是让cur的数值加上前一个节点的数值。

代码如下:

traversal(cur->right);  // 右
cur->val += pre;        // 中
pre = cur->val;
traversal(cur->left);   // 左

递归法整体代码如下:

class Solution {
private:
    int pre; // 记录前一个节点的数值
    void traversal(TreeNode* cur) { // 右中左遍历
        if (cur == NULL) return;
        traversal(cur->right);
        cur->val += pre;
        pre = cur->val;
        traversal(cur->left);
    }
public:
    TreeNode* convertBST(TreeNode* root) {
        pre = 0;
        traversal(root);
        return root;
    }
};

迭代法

迭代法其实就是中序模板题了,在二叉树:前中后序迭代法和二叉树:前中后序统一方式迭代法可以选一种自己习惯的写法。

这里我给出其中的一种,代码如下:

class Solution {
private:
    int pre; // 记录前一个节点的数值
    void traversal(TreeNode* root) {
        stack st;
        TreeNode* cur = root;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;    // 左
            }
        }
    }
public:
    TreeNode* convertBST(TreeNode* root) {
        pre = 0;
        traversal(root);return root;
    }
};

总结

经历了前面各种二叉树增删改查的洗礼之后,这道题目应该比较简单了。

「好了,二叉树已经接近尾声了,接下来就是要对二叉树来一个大总结了」

最后再次祝大家1024节日快乐,哈哈哈!

在留言区留下你的思路吧!

-------end-------

我将算法学习相关的资料已经整理到了Github :https://github.com/youngyangyang04/leetcode-master,里面还有leetcode刷题攻略、各个类型经典题目刷题顺序、思维导图看一看一定会有所收获,如果给你有帮助给一个star支持一下吧!

另外因为公众号改版,时间线被打乱,一些精彩文章大家可能错过了。如果感觉这里的文章对你有帮助, 赶紧给「代码随想录」加一个星标吧,方便第一时间阅读文章 往期 精彩回顾二叉树:构造一棵搜索树二叉树:修剪一棵搜索树二叉树:搜索树中的删除操作二叉树:搜索树中的插入操作二叉树:搜索树的公共祖先问题本周小结!(二叉树系列四)二叉树:公共祖先问题二叉树:我的众数是多少?二叉树:搜索树的最小绝对差二叉树:我是不是一棵二叉搜索树二叉树:二叉搜索树登场!二叉树:合并两个二叉树本周小结!(二叉树系列三)二叉树:构造一棵最大的二叉树二叉树:构造二叉树登场! 「代码随想录」期待你的关注!

每天8:35准时推送一道经典算法题目,推送的每道题目都不是孤立的,而是由浅入深,环环相扣,帮你梳理算法知识脉络,轻松学算法!

a678fb7085e84838989975c932dbbd8f.png 4a3b8bb08a0158894e860bfb3c89be6d.png 刷题可以加我微信! 右边为个人微信,添加时备注:「简单自我介绍」+「组队刷题」我就知道你[在看] 495a87742b114fcf1785ac91bdce7c9a.gif
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值