【发布时间】:2020-11-01 20:20:07
【问题描述】:
我需要最小化内存消耗和计算二叉搜索树范围和的函数的执行时间 (https://leetcode.com/problems/range-sum-of-bst/)。
我目前的结果是:
运行时间:88 毫秒,比 69.00% 的 Go online 提交的 BST 范围和要快。
内存使用:7.9 MB,不到 BST Range Sum 的 Go online 提交的 5.67%。
我当前的代码:
func rangeSumBST(root *TreeNode, min int, max int) int {
sum := 0
arr := []*TreeNode{root}
var node *TreeNode
for len(arr) > 0 {
node = arr[len(arr)-1]
arr = arr[:len(arr)-1]
if node.Val >= min && node.Val <= max {
sum += node.Val
}
if node.Left != nil && node.Val > min {
arr = append(arr, node.Left)
}
if node.Right != nil && node.Val < max {
arr = append(arr, node.Right)
}
}
return sum
}
我尝试以递归方式解决问题,这很优雅,但当然比迭代解决方案更慢且更占用内存。
我所拥有的迭代解决方案尽可能精简和简单。我声明并重用 node 变量,而不是在 for 循环中声明它。我将节点添加到切片的末尾而不是开头。
我还能做些什么来使其更快并使用更少的内存?还是有更有效的算法?或者是 Leetcode 以某种方式错误地测量了执行时间和内存消耗?
【问题讨论】:
-
另外,问题陈述表明:1.树中的节点数最多为10000。2.最终答案保证小于2^31。它与可能的优化有关吗?
-
朴素递归解决方案实际上更快(运行时间:84 毫秒,比 93.67% 的 BST 范围和的 Go 在线提交要快。)但消耗的内存略多。
-
回答你应该分析代码以确定它在哪里花费时间。一种明显的优化是预先分配 arr 而不是分配 JIT。
-
由于它是一个 BST,您可以使用 BST 的 Inorder Morris 遍历在 O(1) 空间复杂度中完成,因此您无法做得比 O(N) 时间复杂度更好。您当前的实现使用的是堆栈,因此在最坏的情况下,您当前的空间复杂度为 O(N),此时树基本上是一条路径。
标签: algorithm go binary-search-tree