力扣日记1.19-【二叉树篇】538. 把二叉搜索树转换为累加树

力扣日记:【二叉树篇】538. 把二叉搜索树转换为累加树

日期:2023.1.19

参考:代码随想录、力扣

ps:因为准备组会汇报又搁置了好久(其实就是懒+逃避T^T),但这是最后一道二叉树啦啊啊啊!!!

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

题目描述

难度:

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

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

  • 节点的左子树仅包含键 小于 节点键的节点。
  • 节点的右子树仅包含键 大于 节点键的节点。
  • 左右子树也必须是二叉搜索树。
    注意:本题和 第1038题 相同

示例 1:

输入:[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 和 10^4 之间。
  • 每个节点的值介于 -10^4 和 10^4 之间。
  • 树中的所有值 互不相同 。
  • 给定的树为二叉搜索树。

题解

cpp 复制代码
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    TreeNode* convertBST(TreeNode* root) {
        traversal(root);    // 遍历完后,每个节点的新值都更新了
        return root;
    }
    // 思路:按照 右中左 的顺序遍历,节点的值加上当前累积值即为新的节点值
    // 并将当前累加值更新为新节点值,相当于累积值边遍历边累加
    int val = 0;    // 记录当前累加值(全局变量,每遍历一个值,会加上现在遍历到的值)
    void traversal(TreeNode* root) {
        // 右中左(逆序)
        if (root == nullptr) return;
        // 右
        traversal(root->right); // 向右递归遍历
        // 中
        root->val += val;   // 当前值加上累积值
        val = root->val;    // 更新累积值(相当于原累积值加上了当前值)
        // 左
        traversal(root->left);  // 向左递归遍历
    }

};

复杂度

时间复杂度:

空间复杂度:

思路总结

  • 思路:按照 右中左 的顺序遍历,节点的值加上当前累积值即为新的节点值,同时将当前累加值更新为新节点值(相当于累积值边遍历边累加)
  • 这个思路是我瞅着示例图模拟老半天才得出的结论(悲),对此,代码随想录提供了一个很好的思路------"(二叉搜索树root = [5,2,13])换一个角度来看,就是一个有序数组[2, 5, 13],求从后到前的累加数组,也就是[20, 18, 13],是不是感觉这就简单了 ",也就是说对该二叉搜索树进行逆向中序遍历(右左中),先遍历到13(13+0=13),再遍历到5,5+13=18为新值,再遍历到2,2+18=20为新值。对示例图中的二叉树也是一样,通过一个值来累积遍历到的节点值,每遍历到一个节点,就加上这个累积值(实际上也是上一个遍历到的节点的新值)作为新节点值即可
  • 所以通过一个递归函数,右中左来进行逆向中序遍历,并用一个全局变量来记录累积值
  • 不要用传递参数或者返回值来记录累积值!!!会相当麻烦,直接用全局变量即可!!!(其实就是一个指向上一个节点的指针
相关推荐
艾莉丝努力练剑29 分钟前
【LeetCode&数据结构】单链表的应用——反转链表问题、链表的中间节点问题详解
c语言·开发语言·数据结构·学习·算法·leetcode·链表
_殊途2 小时前
《Java HashMap底层原理全解析(源码+性能+面试)》
java·数据结构·算法
珊瑚里的鱼5 小时前
LeetCode 692题解 | 前K个高频单词
开发语言·c++·算法·leetcode·职场和发展·学习方法
秋说6 小时前
【PTA数据结构 | C语言版】顺序队列的3个操作
c语言·数据结构·算法
lifallen7 小时前
Kafka 时间轮深度解析:如何O(1)处理定时任务
java·数据结构·分布式·后端·算法·kafka
liupenglove7 小时前
自动驾驶数据仓库:时间片合并算法。
大数据·数据仓库·算法·elasticsearch·自动驾驶
python_tty8 小时前
排序算法(二):插入排序
算法·排序算法
然我8 小时前
面试官:如何判断元素是否出现过?我:三种哈希方法任你选
前端·javascript·算法
F_D_Z9 小时前
【EM算法】三硬币模型
算法·机器学习·概率论·em算法·极大似然估计
秋说9 小时前
【PTA数据结构 | C语言版】字符串插入操作(不限长)
c语言·数据结构·算法