783. Minimum Distance Between BST Nodes(经典)

博客围绕LeetCode题目展开,给出了自己用Python编写的代码和优秀代码。自己的代码采用暴力破解,未利用BST树特性;优秀代码则利用了左子树结点<根结点<右子树结点的特性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

783. Minimum Distance Between BST Nodes

题目

在这里插入图片描述

我的代码

暴力破解,没有利用到BST树的特性。

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

class Solution:
    def minDiffInBST(self, root: TreeNode) -> int:
        li=[]
        def traverse(T):
            if T:
                li.append(T.val)
                traverse(T.left)
                traverse(T.right)
        traverse(root)
        li.sort()
        min_dis=999999999
        for i in range(len(li)-1):
            dis =li[i+1]-li[i]
            if dis<min_dis:
                min_dis=dis
        return min_dis

优秀代码

利用一定的特性,左子树结点<根结点<右子树结点

class Solution:
    def minDiffInBST(self, root: 'TreeNode') -> 'int':
        ans = 0x7fffffff #最大数
        def dfs(root):
            nonlocal ans #非局部变量
            mn = mx = root.val	#存储已经获得的最小值/最大值
            if root.left:	
                ln, lx = dfs(root.left) #左边结点<val
                ans = min(ans, root.val - lx) #求出最小值,然后比较ans
                mn = min(mn, ln) #得到更小的值
                mx = max(mx, lx) #得到更大的值
            if root.right:
                rn, rx = dfs(root.right)
                ans = min(ans, rn - root.val)
                mn = min(mn, rn)
                mx = max(mx, rx)
            return mn, mx # 为了传递归传送作为比较
        dfs(root)
        return ans
<think>我们正在讨论二叉搜索树的前序遍历,用户遇到了返回'undefined'的问题。 根据用户的问题,我们需要理解二叉搜索树的前序遍历执行流程,并找出为什么返回'undefined'(或者输出中包含'u')。 首先,我们需要回顾二叉搜索树的前序遍历: 前序遍历顺序:根节点 -> 左子树 -> 右子树 在实现前序遍历时,通常有两种方式: 1. 递归实现 2. 迭代实现(使用栈) 用户提到返回'undefined',这通常与函数的返回值有关。可能是在遍历过程中,某些函数没有返回值,或者返回值处理不当。 另外,用户提到输出结果为'undefined'(或者可能是字符串中包含'u'),我们需要考虑输出字符串中出现了'undefined'这个字符串,或者控制台打印了undefined。 常见原因: 1. 在遍历函数中,可能没有正确返回遍历结果(例如,使用递归时,没有将子树的遍历结果合并)。 2. 在遍历过程中,可能试图访问未定义的节点属性(比如节点为null时,仍然访问其值,然后拼接字符串,导致出现'undefined'字符串)。 3. 在JavaScript等语言中,如果函数没有返回值,调用它就会得到undefined。如果用户期望遍历函数返回一个字符串,但函数没有返回,则可能得到undefined。 为了更具体,我们需要假设一个代码实现。由于用户没有提供代码,我们可以假设一个典型的递归实现,并分析可能出错的地方。 假设二叉搜索树节点的定义如下: ```javascript class Node { constructor(value) { this.value = value; this.left = null; this.right = null; } } ``` 前序遍历递归实现,返回一个字符串(节点值连接起来的字符串): ```javascript class BinarySearchTree { // ... 其他方法 preOrderTraversal(node) { if (node === null) { return ''; // 或者 return null; 但这里我们希望返回字符串,所以返回空字符串 } let result = node.value.toString(); result += this.preOrderTraversal(node.left); result += this.preOrderTraversal(node.right); return result; } } ``` 但是,如果用户这样调用: ```javascript let tree = new BinarySearchTree(); // 构建树 console.log(tree.preOrderTraversal(tree.root)); ``` 如果树为空,那么函数会返回空字符串(不会返回undefined)。但是,如果我们在递归调用时,没有正确处理空节点,那么可能会出现undefined。 然而,上面的代码中,如果node为null,我们返回空字符串,所以不会出现undefined。 但是,另一种常见的错误实现是: ```javascript preOrderTraversal(node) { if (node === null) { return; // 这里没有返回值,相当于返回undefined } let result = node.value.toString(); result += this.preOrderTraversal(node.left); // 这里调用返回undefined,然后与字符串拼接,会变成"undefined" result += this.preOrderTraversal(node.right); return result; } ``` 当节点为null时,函数返回undefined。那么当递归调用时,如果左子树为空,那么`this.preOrderTraversal(node.left)`返回undefined,然后与字符串result拼接,就会将字符串"undefined"加进去。 因此,如果用户看到输出中有"undefined",那么很可能是因为在递归函数中,当节点为null时没有返回一个字符串(而是返回了undefined),然后这个undefined被拼接进了结果字符串。 另一种可能:用户期望函数返回一个字符串,但可能在某些路径下没有返回值(比如,函数没有返回语句),那么整个函数调用就会返回undefined。 例如: ```javascript preOrderTraversal(node) { if (node) { let result = node.value.toString(); result += this.preOrderTraversal(node.left); result += this.preOrderTraversal(node.right); return result; } // 如果node为null,这里没有返回,所以函数返回undefined } ``` 当树为空时,调用这个函数就会返回undefined。 因此,总结可能的原因: 1. 在递归函数中,当节点为null时,没有返回一个空字符串(而是返回了undefined),然后这个undefined被拼接到字符串中,导致结果字符串中出现了"undefined"。 2. 整个遍历函数在树为空时没有返回任何值(即返回undefined),所以打印出来就是undefined。 解决方案: 确保在节点为null时返回空字符串(如果希望结果是字符串的话),或者确保所有路径都有返回值。 修正后的递归实现(返回字符串): ```javascript preOrderTraversal(node) { if (node === null) { return ''; // 返回空字符串 } let result = node.value.toString(); result += this.preOrderTraversal(node.left); result += this.preOrderTraversal(node.right); return result; } ``` 或者,如果不想返回字符串,而是通过回调函数处理(比如打印),那么可以这样实现(但用户的问题是关于返回值的,所以这种不适用): ```javascript preOrderTraversal(node, callback) { if (node === null) return; callback(node.value); this.preOrderTraversal(node.left, callback); this.preOrderTraversal(node.right, callback); } ``` 但是,如果用户使用这种回调方式,那么函数本身没有返回值,所以调用这个函数会返回undefined(但用户期望的是打印节点值,而不是返回值)。所以用户如果错误地打印了函数的返回值,就会得到undefined。 因此,用户需要检查自己的代码: 1. 遍历函数是否在所有路径都有返回值(特别是节点为null时)? 2. 是否在递归调用时,将返回值正确拼接(而不是直接忽略返回值)? 3. 是否在调用遍历函数时,期望得到一个字符串,但实际得到undefined(比如树为空时)? 根据用户的问题描述,我们无法看到具体代码,但以上是常见的错误。 如果用户的问题是关于为什么输出字符串中包含'u',那很可能是因为在字符串拼接时,undefined被转换成了字符串"undefined",所以输出中会有字母'u'(即"undefined"的第一个字母)或者整个单词。 因此,用户应该检查递归函数中对于空节点的处理,确保返回一个空字符串(或者根据情况返回其他不会导致问题的值)。 如果用户能提供具体的代码,我们可以更精确地定位问题。 现在,根据要求,生成相关问题: 1. 二叉搜索树的前序遍历递归实现中,如何处理空节点以避免返回undefined? 2. 二叉搜索树的前序遍历迭代实现与递归实现有何不同? 3. 如何避免在二叉搜索树的遍历过程中出现未定义的节点访问?</think>### 二叉搜索树前序遍历流程与 "undefined" 问题分析 二叉搜索树(BST)的前序遍历遵循 **根节点 → 左子树 → 右子树** 的顺序。当遍历结果出现 `undefined`(或输出字符 `'u'`)时,通常由以下原因导致: --- ### 前序遍历标准流程 1. **访问根节点**:处理当前节点的值 2. **遍历左子树**:递归调用左子树 3. **遍历右子树**:递归调用右子树 伪代码表示: ```javascript function preOrder(node) { if (node === null) return; // 递归终止条件 console.log(node.value); // 1. 访问根 preOrder(node.left); // 2. 遍历左子树 preOrder(node.right); // 3. 遍历右子树 } ``` --- ### 输出 "undefined" 的常见原因 #### 1. **未处理空节点(最常见)** - **问题代码**: ```javascript function preOrder(node) { console.log(node.value); // 当 node=null 时访问 .value 导致 undefined preOrder(node.left); preOrder(node.right); } ``` - **原因**:未检查节点是否为 `null` 时直接访问 `node.value` - **修复**:添加空节点检查 ```javascript function preOrder(node) { if (node === null) return; // 终止递归 console.log(node.value); preOrder(node.left); preOrder(node.right); } ``` #### 2. **返回值未正确处理** - **问题场景**:尝试拼接字符串时遇到空节点 ```javascript function preOrder(node) { if (!node) return; let result = node.value; result += preOrder(node.left); // 递归无返回值 → 拼接 undefined result += preOrder(node.right); return result; } ``` - **修复方案**: ```javascript function preOrder(node) { if (!node) return ""; return node.value + preOrder(node.left) + preOrder(node.right); } ``` #### 3. **异步操作未处理(如 Promise)** - **问题代码**: ```javascript async function preOrder(node) { if (!node) return; console.log(await node.value); // 若 value 未定义异步数据 preOrder(node.left); preOrder(node.right); } ``` - **修复**:确保异步数据已解析 ```javascript async function preOrder(node) { if (!node) return; const value = await fetchValue(node); // 确保数据就绪 console.log(value); await preOrder(node.left); await preOrder(node.right); } ``` --- ### 调试建议 1. **打印节点对象**:`console.log(node)` 替代 `console.log(node.value)`,检查是否出现 `null` 2. **添加追踪日志**: ```javascript function preOrder(node, depth=0) { if (!node) { console.log(`${" ".repeat(depth)}→ null`); return; } console.log(`${" ".repeat(depth)}→ ${node.value}`); preOrder(node.left, depth+1); preOrder(node.right, depth+1); } ``` 3. **验证树结构**:检查是否有节点的 `left`/`right` 指针未正确初始化为 `null` > **关键点**:`undefined` 本质是 **访问了不存在节点的属性** 或 **函数未返回有效值**。通过严格检查空节点和返回值路径即可解决[^1]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值