【LeetCode 每日一题】面试题 17.12. BiNode

Problem: 面试题 17.12. BiNode

文章目录

  • [1. 整体思路](#1. 整体思路)
  • [2. 完整代码](#2. 完整代码)
  • [3. 时空复杂度](#3. 时空复杂度)
      • [时间复杂度: O ( N ) O(N) O(N)](#时间复杂度: O ( N ) O(N) O(N))
      • [空间复杂度: O ( H ) O(H) O(H)](#空间复杂度: O ( H ) O(H) O(H))

1. 整体思路

核心逻辑

  1. 中序遍历 (In-order Traversal)

    • 因为输入是二叉搜索树 (BST),通过中序遍历(左 -> 根 -> 右),我们可以按从小到大的顺序访问所有节点。
    • 这个顺序正是我们需要构建的链表的顺序。
  2. 链表构建 (Pointer Manipulation)

    • 使用一个哨兵节点(Dummy Head)head 来简化链表头部的处理。
    • 使用一个全局变量 pre 来记录中序遍历过程中上一个访问的节点
    • 在遍历到当前节点 node 时:
      • 将上一个节点 preright 指针指向当前节点 node(建立链表连接)。
      • 将当前节点 nodeleft 指针置空(题目要求)。
      • 更新 pre 为当前节点,以便处理下一个节点。
  3. 递归实现

    • 标准的递归 DFS 实现中序遍历:dfs(left) -> 处理当前 -> dfs(right)

2. 完整代码

java 复制代码
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    // 创建一个哨兵节点 head,它的值不重要 (-1)
    // 它的 right 指针将指向最终链表的头节点
    TreeNode head = new TreeNode(-1);
    
    // pre 用于记录中序遍历中的"前驱节点"
    // 初始为 null,或者也可以指向 head,取决于具体实现逻辑
    TreeNode pre = null;

    public TreeNode convertBiNode(TreeNode root) {
        // 开始中序遍历
        dfs(root);
        // 返回哨兵节点的右孩子,即链表的真正头节点
        return head.right;
    }

    // 中序遍历辅助函数
    private void dfs(TreeNode node) {
        // 递归终止条件:节点为空
        if (node == null) {
            return;
        }

        // 1. 递归处理左子树
        dfs(node.left);

        // 2. 处理当前节点 (核心链表构建逻辑)
        if (pre == null) {
            // 如果 pre 为空,说明当前 node 是中序遍历访问的第一个节点(整棵树最小的节点)
            // 它应该是链表的头,所以让 head.right 指向它
            // 同时初始化 pre 指向当前节点
            pre = node;
            head.right = node;
        } else {
            // 如果 pre 不为空,说明之前已经访问过节点
            // 将前驱节点 pre 的 right 指针指向当前节点 node,建立链表连接
            pre.right = node;
            // 更新 pre 指向当前节点,为下一次连接做准备
            pre = node;
        }
        
        // 题目要求:所有节点的 left 指针必须置为 null
        // 这一步非常重要,否则结果不是纯粹的单向链表,可能保留树的结构导致判题错误或循环引用
        node.left = null;

        // 3. 递归处理右子树
        dfs(node.right);
    }
}

3. 时空复杂度

假设二叉树的节点总数为 N N N。

时间复杂度: O ( N ) O(N) O(N)

  • 计算依据
    • 这是一个标准的深度优先搜索(DFS)遍历。
    • 每个节点被访问且仅被访问一次。
    • 在每个节点上的操作(修改指针、判断)都是 O ( 1 ) O(1) O(1) 的常数操作。
  • 结论 : O ( N ) O(N) O(N)。

空间复杂度: O ( H ) O(H) O(H)

  • 计算依据
    • 代码是就地修改(In-place)树的指针,没有创建新的节点列表。
    • 主要的额外空间消耗来自于递归调用栈
    • 递归深度取决于树的高度 H H H。
    • 最坏情况(退化为链表): O ( N ) O(N) O(N)。
    • 最好/平均情况(平衡树): O ( log ⁡ N ) O(\log N) O(logN)。
  • 结论 : O ( N ) O(N) O(N)(最坏情况)。
相关推荐
刘大猫.2 小时前
XNMS项目-拓扑图展示
java·人工智能·算法·拓扑·拓扑图·节点树·xnms
夏鹏今天学习了吗3 小时前
【LeetCode热题100(95/100)】寻找重复数
算法·leetcode·职场和发展
TTGGGFF7 小时前
控制系统建模仿真(四):线性控制系统的数学模型
人工智能·算法
晚风吹长发7 小时前
初步了解Linux中的命名管道及简单应用和简单日志
linux·运维·服务器·开发语言·数据结构·c++·算法
圣保罗的大教堂7 小时前
leetcode 3315. 构造最小位运算数组 II 中等
leetcode
Σίσυφος19008 小时前
Halcon中霍夫直线案例
算法
Anastasiozzzz8 小时前
leetcode力扣hot100困难题--4.俩个正序数列的中位数
java·算法·leetcode·面试·职场和发展
BHXDML8 小时前
第六章:推荐算法
算法·机器学习·推荐算法
Tisfy9 小时前
LeetCode 3510.移除最小数对使数组有序 II:有序集合
算法·leetcode·题解·设计·有序集合