Leetcode Python超琐碎笔记: 938. Range Sum of BST

超琐碎 ≈ 完整记录 + 深入探究 + 任性吐槽

问题地址,难度:Normal,标签:Tree

若有错误之处请予以指正:)

问题描述

Given the root node of a binary search tree, return the sum of values of all nodes with value between L and R (inclusive).

The binary search tree is guaranteed to have unique values.

Example 1:
Input: root = [10,5,15,3,7,null,18], L = 7, R = 15
Output: 32

Example 2:
Input: root = [10,5,15,3,7,13,18,1,null,6], L = 6, R = 10
Output: 23

Note:

The number of nodes in the tree is at most 10000.
The final answer is guaranteed to be less than 2^31.

题意分析

这道题需要了解二叉搜索树的定义,以及递归/循环的知识。

我的实现及调优过程

方法1:356 ms

方法1我的思路是先看[L, R]这个range能不能卡住当前节点,即当前节点值v[L,R]内。

  • 如果在[L,R]内,当前的range_sum = (v + 左子树range_sum + 右子树rang_sum)
  • 如果不在[L,R]
    • 如果整个[L,R]都在v右边,那么:当前的range_sum = 右子树range_sum
    • 如果整个[L,R]都在v左边,那么:当前的range_sum = 左子树range_sum

这样从根节点向下,每一个被遍历节点的range_sum都被算出来,最后加回到根节点。注意不是所有节点都会被遍历,因为v不在[L,R]内的情况下,接下去只会看其左右子树之一。

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def rangeSumBST(self, root, L, R):
        """
        :type root: TreeNode
        :type L: int
        :type R: int
        :rtype: int
        """
        range_sum = getRangeSum(root, L, R)
        return range_sum
        
def getRangeSum(node, L, R):
    if node is None:
        return 0
    if node.val > R:
        range_sum = getRangeSum(node.left, L, R)
    elif node.val < L:
        range_sum = getRangeSum(node.right, L, R)
    else:
        range_sum = node.val + \
                    getRangeSum(node.left, L, R) + \
                    getRangeSum(node.right, L, R)
    return range_sum
  • 时间复杂度:O(n) (n为树的节点数,最坏情况下每个节点都被遍历)
  • 空间复杂度:O(m) (递归本身的栈会占用一些资源,m为树的深度,影响栈的数量)
方法2:356 ms

方法2是Leetcode上的Solution,思路是先初始化了一个self.ans为0,然后逐个遍历节点,每遇到一个在[L,R]内的节点,就做一次加法累进self.ans

具体的做法:

  1. 判断当前节点是否在[L,R]内,在的话self.ans加上当前节点值,不在的话继续步骤2和3
  2. 判断左子树是否可能存在符合要求的节点。根据二叉搜索树定义,左子树中任意的节点w都满足w<v,而我们要的节点要求是[L, R]如果L<v,那么可能存在w>=L,即w落在[L, v)范围内,这时只要再满足w<=R(v<=R OR w<=R)w就落进了[L,R]。注意须同时满足三个条件:L<v AND w>=L AND (v<=R OR w<=R),第一个条件使用if确保,但由于我们在该步还没有访问w,无法确定第二、三个条件的真假,所以继续搜索左子树
  3. 同样地,考虑与2中相似的情况,我们在该步无法判断w<=R的真假,所以继续搜索右子树

注意这种方法同样不一定会遍历所有节点。同时可以看到,这种解法的实现逻辑看似比上一种简单,但是需要经过严密的分析才能证明其正确性。另外引用王垠的观点,这种连续几个if没有else的写法也是有风险的(终于为自己为什么没有想到这种解法找到了充分理由LOL)

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution(object):
    def rangeSumBST(self, root, L, R):
        def dfs(node):
            if node:
                if L <= node.val <= R:
                    self.ans += node.val
                if L < node.val:
                    dfs(node.left)
                if node.val < R:
                    dfs(node.right)

        self.ans = 0
        dfs(root)
        return self.ans
  • 时间复杂度:O(n) (n为树的节点数,最坏情况下每个节点都被遍历)
  • 空间复杂度:O(m) (递归本身的栈会占用一些资源,m为树的深度,影响栈的数量)
方法3:227 ms
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def rangeSumBST(self, root: Optional[TreeNode], low: int, high: int) -> int:
        def rangeSum(t):
            _sum = 0
            if not t:
                return _sum
            elif t.val < low:
                _sum += rangeSum(t.right)
            elif t.val > high:
                _sum += rangeSum(t.left)
            else:
                _sum += t.val + rangeSum(t.left) + rangeSum(t.right)
            return _sum
        return rangeSum(root)

2022重刷,思路同1,接口简单一点

  • 时间复杂度:O(n) (n为树的节点数,最坏情况下每个节点都被遍历)
  • 空间复杂度:O(m) (递归本身的栈会占用一些资源,m为树的深度,影响栈的数量)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,425评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,058评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,186评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,848评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,249评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,554评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,830评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,536评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,239评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,505评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,004评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,346评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,999评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,060评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,821评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,574评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,480评论 2 267

推荐阅读更多精彩内容