从二叉搜索树到更大和树 : BST 中序遍历的经典运用

题目描述

这是 LeetCode 上的 1038. 从二叉搜索树到更大和树 ,难度为 中等

Tag : 「BST」、「中序遍历」

给定一个二叉搜索树 root (BST),请将它的每个节点的值替换成树中大于或者等于该节点值的所有节点值之和。

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

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

示例 1:

csharp 复制代码
输入:[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:

ini 复制代码
输入:root = [0,null,1]

输出:[1,null,1]

提示:

  • 树中的节点数在 1 , 100 1, 100 1,100 范围内。
  • 0 < = N o d e . v a l < = 100 0 <= Node.val <= 100 0<=Node.val<=100
  • 树中的所有值均不重复 。

中序遍历

利用 BST 的中序遍历是有序 的特性,我们可以通过两次遍历 BST 来求解问题。

首先,通过一次遍历,计算出整棵树的节点总和 tot,然后在中序遍历过程中,不断对 tot 进行更新,将其作为当前未遍历到的节点的总和,用于给当前节点赋值。

假设当前遍历到的节点为 x(起始节点值为 t),那么将节点更新为当前节点 tot 后,更新 tot = tot - t

这是常规的中序遍历做法,更进一步,如果将其中序遍历的顺序进行翻转(从「左中右」调整为「右中左」),则可实现一次遍历。

Java 代码:

Java 复制代码
class Solution {
    int tot = 0;
    public TreeNode bstToGst(TreeNode root) {
        dfs(root);
        return root;
    }
    void dfs(TreeNode root) {
        if (root == null) return ;
        dfs(root.right);
        tot += root.val;
        root.val = tot;
        dfs(root.left);
    }
}

C++ 代码:

C++ 复制代码
class Solution {
public:
    int tot = 0;
    TreeNode* bstToGst(TreeNode* root) {
        dfs(root);
        return root;
    }
    void dfs(TreeNode* root) {
        if (root == nullptr) return;
        dfs(root->right);
        tot += root->val;
        root->val = tot;
        dfs(root->left);
    }
};

Python 代码:

Python 复制代码
class Solution:
    def bstToGst(self, root: TreeNode) -> TreeNode:
        tot = 0
        def dfs(root):
            nonlocal tot
            if not root: return
            dfs(root.right)
            tot += root.val
            root.val = tot
            dfs(root.left)
        dfs(root)
        return root

TypeScript 代码:

TypeScript 复制代码
function bstToGst(root: TreeNode | null): TreeNode | null {
    let tot = 0;
    const dfs = function(root: TreeNode | null): void {
        if (!root) return ;
        dfs(root.right);
        tot += root.val;
        root.val = tot;
        dfs(root.left);
    }
    dfs(root);
    return root;
};
  • 时间复杂度: O ( n ) O(n) O(n)
  • 空间复杂度: O ( n ) O(n) O(n)

最后

这是我们「刷穿 LeetCode」系列文章的第 No.1038 篇,系列开始于 2021/01/01,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先把所有不带锁的题目刷完。

在这个系列文章里面,除了讲解解题思路以外,还会尽可能给出最为简洁的代码。如果涉及通解还会相应的代码模板。

为了方便各位同学能够电脑上进行调试和提交代码,我建立了相关的仓库:github.com/SharingSour...

在仓库地址里,你可以看到系列文章的题解链接、系列文章的相应代码、LeetCode 原题链接和其他优选题解。

更多更全更热门的「笔试/面试」相关资料可访问排版精美的 合集新基地 🎉🎉

相关推荐
腻害兔10 分钟前
【若依项目-产品经理视角】RuoYi-Vue-Pro 源码拆解:ERP 企业资源模块,一个轻量级进销存的完整实现?
前端·javascript·vue.js·人工智能·前端框架·产品经理·ai编程
虹科网络安全21 分钟前
艾体宝新闻|从 SQL 注入到服务器接管:CVE-2026-57517 暴露 Web 管理面板的供应链与安全编码风险
服务器·前端·sql
济*沧*海25 分钟前
如何判断接口的返回值?
后端
糖果店的幽灵27 分钟前
langgraph的四种state解析
java·前端·javascript·langgraph
杨充30 分钟前
5.多用组合和少继承
后端
杨充35 分钟前
4.接口而非实现编程
java·后端·架构
顺颂时绥_141 分钟前
前端大图片压缩与安卓/苹果设备矫正实践
前端
Csvn44 分钟前
JSON.parse 大数精度丢失:一个让前后端互相甩锅的 Bug
前端
一缕清烟在人间1 小时前
HarmonyOS应用开发实战:萌宠日记 - 生命周期在萌宠日记中的实践
后端
Conan在掘金1 小时前
鸿蒙 ArkUI 组件深水区:Span 富文本嵌套,一行 Text 塞下「红蓝斜下大」五样式 + 动态高亮
后端