【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)(最坏情况)。
相关推荐
A尘埃9 分钟前
超市购物篮关联分析与货架优化(Apriori算法)
算法
.小墨迹16 分钟前
apollo学习之借道超车的速度规划
linux·c++·学习·算法·ubuntu
不穿格子的程序员26 分钟前
从零开始刷算法——贪心篇1:跳跃游戏1 + 跳跃游戏2
算法·游戏·贪心
大江东去浪淘尽千古风流人物29 分钟前
【SLAM新范式】几何主导=》几何+学习+语义+高效表示的融合
深度学习·算法·slam
铉铉这波能秀37 分钟前
LeetCode Hot100数据结构背景知识之列表(List)Python2026新版
数据结构·leetcode·list
重生之我是Java开发战士43 分钟前
【优选算法】模拟算法:替换所有的问号,提莫攻击,N字形变换,外观数列,数青蛙
算法
仟濹1 小时前
算法打卡 day1 (2026-02-06 周四) | 算法: DFS | 1_卡码网98 可达路径 | 2_力扣797_所有可能的路径
算法·leetcode·深度优先
yang)1 小时前
欠采样时的相位倒置问题
算法
历程里程碑1 小时前
Linux20 : IO
linux·c语言·开发语言·数据结构·c++·算法
A尘埃1 小时前
物流公司配送路径动态优化(Q-Learning算法)
算法