Python算法题集_验证二叉搜索树

本文详细解析了如何使用Python验证二叉搜索树,介绍了标准DFS递归、改进版DFS+终止检测以及BFS迭代+终止检测三种方法,并展示了它们的性能对比。最优解为BFS迭代法,具有较低的时间复杂度和内存使用。
摘要由CSDN通过智能技术生成

本文为Python算法题集之一的代码示例

题98:验证二叉搜索树

1. 示例说明

  • 给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。

    有效 二叉搜索树定义如下:

    • 节点的左子树只包含 小于 当前节点的数。
    • 节点的右子树只包含 大于 当前节点的数。
    • 所有左子树和右子树自身必须也是二叉搜索树。

    示例 1:

    img

    输入:root = [2,1,3]
    输出:true
    

    示例 2:

    img

    输入:root = [5,1,4,null,null,3,6]
    输出:false
    解释:根节点的值是 5 ,但是右子节点的值是 4 。
    

    提示:

    • 树中节点数目范围在[1, 104]
    • -231 <= Node.val <= 231 - 1

2. 题目解析

- 题意分解

  1. 本题为二叉搜索树的验证
  2. 基本的设计思路是进行二叉树的中序遍历,基本的思路是深度优先算法【DFS(Depth-First Search)】、广度有限算法【BFS(Breadth-First Search)】
  3. 检查中序遍历的结果是否为有序的,如果有序就是二叉搜索树

- 优化思路

  1. 通常优化:减少循环层次

  2. 通常优化:增加分支,减少计算集

  3. 通常优化:采用内置算法来提升计算速度

  4. 分析题目特点,分析最优解

    1. 可以考虑采用DFS、BFS进行中序遍历

    2. 可以在过程中进行终止条件判断,减少不必要的遍历计算


- 测量工具

  • 本地化测试说明:LeetCode网站测试运行时数据波动很大,因此需要本地化测试解决这个问题
  • CheckFuncPerf(本地化函数用时和内存占用测试模块)已上传到CSDN,地址:Python算法题集_检测函数用时和内存占用的模块
  • 本题本地化超时测试用例自己生成,详见【最优算法章节】

3. 代码展开

1) 标准求解【DFS递归】

先进行DFS递归求解,然后进行有序判断

马马虎虎,超过45%在这里插入图片描述

import CheckFuncPerf as cfp

class Solution:
 def isValidBST_base(self, root):
     def inorderTraversal_dfs(root):
         if not root:
             return []
         return inorderTraversal_dfs(root.left) + [root.val] + inorderTraversal_dfs(root.right)
     list_node = inorderTraversal_dfs(root)
     for iIdx in range(len(list_node)-1):
         if list_node[iIdx] >= list_node[iIdx+1]:
             return False
     return True

aroot = sortedArrayToBST(nums)
aSolution = Solution()
result = cfp.getTimeMemoryStr(Solution.isValidBST_base, aSolution, aroot)
print(result['msg'], '执行结果 = {}'.format(result['result']))

# 运行结果
函数 isValidBST_base 的运行时间为 317.15 ms;内存使用量为 112.00 KB 执行结果 = False

2) 改进版一【DFS递归+终止检测】

在DFS递归中进行终止检测

性能卓越,超过97%在这里插入图片描述

import CheckFuncPerf as cfp

class Solution:
 def isValidBST_ext1(self, root):
     def inOrder(root, result):
         if root == None:
             return True
         if inOrder(root.left, result) == False:
             return False
         if result and result[-1] >= root.val:
             return False
         result.append(root.val)
         if inOrder(root.right, result) == False:
             return False
         return True
     list_node = []
     return inOrder(root, list_node)

aroot = sortedArrayToBST(nums)
aSolution = Solution()
result = cfp.getTimeMemoryStr(Solution.isValidBST_ext1, aSolution, aroot)
print(result['msg'], '执行结果 = {}'.format(result['result']))

# 运行结果
函数 isValidBST_ext1 的运行时间为 12.99 ms;内存使用量为 8.00 KB 执行结果 = False

3) 改进版二【BFS迭代+终止检测】

采用堆栈实现BFS算法,在遍历过程中进行终止条件检测

性能优越,超过90%在这里插入图片描述

import CheckFuncPerf as cfp

class Solution:
 def isValidBST_ext2(self, root):
     if not root:
         return True
     list_stack = []
     list_node = []
     while root or list_stack:
         if root:
             list_stack.append(root)
             root = root.left
         else:
             curnode = list_stack.pop()
             if list_node:
                 if curnode.val <= list_node[-1]:
                     return False
             list_node.append(curnode.val)
             root = curnode.right
     return True

aroot = sortedArrayToBST(nums)
aSolution = Solution()
result = cfp.getTimeMemoryStr(Solution.isValidBST_ext1, aSolution, aroot)
print(result['msg'], '执行结果 = {}'.format(result['result']))

# 运行结果
函数 isValidBST_ext2 的运行时间为 9.97 ms;内存使用量为 568.00 KB 执行结果 = False

4. 最优算法

根据本地日志分析,最优算法为第3种方式【BFS迭代+终止检测】isValidBST_ext2

iLen = 1000000
nums = [x for x in range(iLen)]
nums[499995], nums[50005] = nums[50005], nums[499995]
def sortedArrayToBST(nums):
    if not nums:
        return
    mid = len(nums) // 2
    root = TreeNode(nums[mid])
    if mid == 0:
        return root
    root.left = sortedArrayToBST(nums[:mid])
    root.right = sortedArrayToBST(nums[mid+1:])
    return root
aroot = sortedArrayToBST(nums)
aSolution = Solution()
result = cfp.getTimeMemoryStr(Solution.isValidBST_base, aSolution, aroot)
print(result['msg'], '执行结果 = {}'.format(result['result']))
result = cfp.getTimeMemoryStr(Solution.isValidBST_ext1, aSolution, aroot)
print(result['msg'], '执行结果 = {}'.format(result['result']))
result = cfp.getTimeMemoryStr(Solution.isValidBST_ext2, aSolution, aroot)
print(result['msg'], '执行结果 = {}'.format(result['result']))

# 算法本地速度实测比较
函数 isValidBST_base 的运行时间为 317.15 ms;内存使用量为 112.00 KB 执行结果 = False
函数 isValidBST_ext1 的运行时间为 12.99 ms;内存使用量为 8.00 KB 执行结果 = False
函数 isValidBST_ext2 的运行时间为 9.97 ms;内存使用量为 568.00 KB 执行结果 = False

一日练,一日功,一日不练十日空

may the odds be ever in your favor ~

  • 48
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

长孤秋落

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值