Algorithm 最小化二叉树范围和的内存消耗和执行时间
我需要最小化计算二叉搜索树()的范围和的函数的内存消耗和执行时间 我目前的结果是: 运行时间:88毫秒,比BST范围总和的上网提交的69.00%快 内存使用率:7.9 MB,不到BST范围总和在线提交的5.67% 我当前的代码:Algorithm 最小化二叉树范围和的内存消耗和执行时间,algorithm,go,binary-search-tree,Algorithm,Go,Binary Search Tree,我需要最小化计算二叉搜索树()的范围和的函数的内存消耗和执行时间 我目前的结果是: 运行时间:88毫秒,比BST范围总和的上网提交的69.00%快 内存使用率:7.9 MB,不到BST范围总和在线提交的5.67% 我当前的代码: func rangeSumBST(根*TreeNode,最小整数,最大整数)整数{ 总和:=0 arr:=[]*树节点{root} 变量节点*树节点 对于len(arr)>0{ 节点=arr[len(arr)-1] arr=arr[:len(arr)-1] 如果node
func rangeSumBST(根*TreeNode,最小整数,最大整数)整数{
总和:=0
arr:=[]*树节点{root}
变量节点*树节点
对于len(arr)>0{
节点=arr[len(arr)-1]
arr=arr[:len(arr)-1]
如果node.Val>=min&&node.Val-min{
arr=append(arr,node.Left)
}
如果node.Right!=nil&&node.Val
我试着递归地解决这个问题,这很优雅,但当然比迭代的解决方案更慢、更需要内存
我所拥有的迭代解决方案尽可能精简和简单。我声明并重用节点
变量,而不是在for循环中声明它。我将节点添加到切片的末尾,而不是开始
我还可以做些什么来加快速度和减少内存使用?还是有更有效的算法?还是Leetcode测量执行时间和内存消耗的方式有误?由于它是一个BST,您可以使用在O(1)空间复杂度中执行。对于BST,在Order Morris Travers中,对于单个查询,您不能比O(N)时间复杂度做得更好,除非在树本身中进行某种预处理。您当前的实现使用堆栈,所以在最坏的情况下,当树基本上是一条路径时,您当前的空间复杂度是O(N) 在Go中的实施(能够击败99%):
func rangeSumBST(root *TreeNode, min int, max int) int {
if root == nil {
return 0
}
var pre *TreeNode
curr := root
sum := 0
for curr != nil {
if curr.Left == nil {
if curr.Val >= min && curr.Val <= max {
sum += curr.Val
}
if curr.Val > max {
break
}
curr = curr.Right
} else {
pre = curr.Left
for pre.Right != nil && pre.Right != curr {
pre = pre.Right
}
if pre.Right == nil {
pre.Right = curr
curr = curr.Left
} else {
pre.Right = nil
if curr.Val >= min && curr.Val <= max {
sum += curr.Val
}
if curr.Val > max {
break
}
curr = curr.Right
}
}
}
return sum
}
func rangeSumBST(根*TreeNode,最小整数,最大整数)整数{
如果根==nil{
返回0
}
前*树节点变量
curr:=根
总和:=0
对于curr!=零{
如果当前左侧==零{
如果当前值>=最小值和当前值最大值(&C){
打破
}
当前=当前对
}否则{
前=当前左侧
对于右前!=零和右前!=当前{
pre=pre.Right
}
如果前右==nil{
前右=当前
当前=当前左侧
}否则{
前右=零
如果当前值>=最小值和当前值最大值(&C){
打破
}
当前=当前对
}
}
}
回报金额
}
时间复杂度:O(节点数)
空间复杂性:O(1)
注意:不知何故,它并没有显示内存性能的任何改善,可能是因为测试还不够,并且已知leetcode在测试不太大时会显示以前提交的解决方案的旧统计信息。因为它是一个BST,您可以在O(1)中执行空间复杂度使用对于BST,在Order Morris Travers中,除非对树本身进行某种预处理,否则单次查询的时间复杂度不能超过O(N)。您当前的实现使用堆栈,所以在最坏的情况下,当树基本上是一条路径时,您当前的空间复杂度是O(N) 在Go中的实施(能够击败99%):
func rangeSumBST(root *TreeNode, min int, max int) int {
if root == nil {
return 0
}
var pre *TreeNode
curr := root
sum := 0
for curr != nil {
if curr.Left == nil {
if curr.Val >= min && curr.Val <= max {
sum += curr.Val
}
if curr.Val > max {
break
}
curr = curr.Right
} else {
pre = curr.Left
for pre.Right != nil && pre.Right != curr {
pre = pre.Right
}
if pre.Right == nil {
pre.Right = curr
curr = curr.Left
} else {
pre.Right = nil
if curr.Val >= min && curr.Val <= max {
sum += curr.Val
}
if curr.Val > max {
break
}
curr = curr.Right
}
}
}
return sum
}
func rangeSumBST(根*TreeNode,最小整数,最大整数)整数{
如果根==nil{
返回0
}
前*树节点变量
curr:=根
总和:=0
对于curr!=零{
如果当前左侧==零{
如果当前值>=最小值和当前值最大值(&C){
打破
}
当前=当前对
}否则{
前=当前左侧
对于右前!=零和右前!=当前{
pre=pre.Right
}
如果前右==nil{
前右=当前
当前=当前左侧
}否则{
前右=零
如果当前值>=最小值和当前值最大值(&C){
打破
}
当前=当前对
}
}
}
回报金额
}
时间复杂度:O(节点数)
空间复杂性:O(1)
注意:不知何故,它并没有显示内存性能的任何改善,可能是因为测试不够,并且已知leetcode在测试规模不太大时会显示以前提交的解决方案的旧统计信息。此外,问题陈述显示:1。树中的节点数最多为10000。2.最终答案保证小于2^31。这与可能的优化有关吗?朴素的递归解决方案实际上更快(运行时间:84毫秒,比BST范围和的93.67%的在线提交速度快),但会消耗稍多的内存。要回答这个问题,您应该分析代码以找出它在哪里花费时间。一个明显的优化是预分配arr,而不是分配JIT。由于这是一个BST,您可以使用BST的有序Morris遍历在O(1)空间复杂度内完成,因此您不能比O(N)时间复杂度做得更好。您当前的实现使用的是堆栈,所以在最坏的情况下,当树基本上是一条路径时,您当前的空间复杂度是O(N)。树中的节点数最多为10000。2.最终答案保证小于2^31。这与可能的优化有关吗?简单的递归解决方案实际上更快(运行时间:84毫秒,比BST范围和的93.67%的在线提交速度快),但会消耗稍多的内存