leetcode
leetcode 2801 ~ 2850
BiNode

BiNode

难度:

标签:

题目描述

The data structure TreeNode is used for binary tree, but it can also used to represent a single linked list (where left is null, and right is the next node in the list). Implement a method to convert a binary search tree (implemented with TreeNode) into a single linked list. The values should be kept in order and the operation should be performed in place (that is, on the original data structure).

Return the head node of the linked list after converting.

Note: This problem is slightly different from the original one in the book.

 

Example:

Input:  [4,2,5,1,3,null,6,0]
Output:  [0,null,1,null,2,null,3,null,4,null,5,null,6]

Note:

  • The number of nodes will not exceed 100000.

代码结果

运行时间: 48 ms, 内存: 22.9 MB


/*
思路:
1. 使用Java Stream API的collect方法,将BST的节点收集到一个List中。
2. 遍历List,将节点的左指针设为null,右指针设为下一个节点。
3. 返回转换后的单向链表的头节点。
*/

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Solution {
    public TreeNode flatten(TreeNode root) {
        List<TreeNode> nodes = new ArrayList<>();
        inorderTraversal(root, nodes);
        for (int i = 0; i < nodes.size() - 1; i++) {
            nodes.get(i).left = null;
            nodes.get(i).right = nodes.get(i + 1);
        }
        if (!nodes.isEmpty()) {
            nodes.get(nodes.size() - 1).left = null;
            nodes.get(nodes.size() - 1).right = null;
            return nodes.get(0);
        }
        return null;
    }

    private void inorderTraversal(TreeNode node, List<TreeNode> nodes) {
        if (node == null) return;
        inorderTraversal(node.left, nodes);
        nodes.add(node);
        inorderTraversal(node.right, nodes);
    }
}

解释

方法:

这个题解采用了深度优先搜索(DFS)的方法,特别是中序遍历,来实现二叉搜索树到单向链表的转换。中序遍历的顺序是左-根-右,这正好符合二叉搜索树的节点值从小到大的顺序。在遍历过程中,每访问一个节点,就将其左子节点设为空,并将其与前一个访问的节点(pre)的右子节点连接起来。如果是遍历到的第一个节点,则将其设置为链表的头节点。通过这种方式,可以在遍历结束时得到一个单向链表,链表中的节点顺序与二叉搜索树的中序遍历顺序相同。

时间复杂度:

O(n)

空间复杂度:

O(n)

代码细节讲解

🦆
在转换过程中,为什么要将当前节点的左子节点设为空,这样做的目的是什么?
在将二叉搜索树转换为单向链表的过程中,将当前节点的左子节点设为空是为了断开原来的二叉树结构,使每个节点只保留向右的连接。这样做的目的是确保转换后的结构不再是二叉树,而是形成一个单向链表。在单向链表中,每个节点只有一个指向下一个节点的连接(即右子节点),而没有向左的连接。这样可以保持链表的单向性质,同时也保证了链表中元素的顺序与二叉搜索树的中序遍历顺序一致,即从小到大。
🦆
递归函数`dfs`在遍历结束后如何确保所有节点都正确连接成单向链表?具体是通过哪些步骤实现的?
递归函数`dfs`通过以下步骤确保所有节点都正确连接成单向链表:1. 首先递归遍历左子树,这样可以确保按照中序遍历的顺序访问每个节点。2. 访问当前节点时,将其左子节点设为空,断开左侧的连接。3. 检查是否存在前一个访问的节点(`pre`),如果存在,则将前一个节点的右子节点指向当前节点,从而连接前一个节点与当前节点。4. 如果`pre`不存在,说明当前节点是遍历的第一个节点,将其设置为链表的头节点。5. 更新`pre`为当前节点,以便在后续的遍历中将其作为前一个节点使用。6. 最后递归遍历右子树。通过这种方式,每个节点在访问时都正确地连接到链表中,从而在遍历结束时形成一个完整的单向链表。
🦆
如何处理二叉搜索树中的空节点,它们在转换过程中有什么特殊的影响吗?
在二叉搜索树中的空节点在转换过程中不需要进行特殊处理。在递归函数`dfs`中,一旦遇到一个空节点,函数将直接返回并不执行任何操作。这意味着空节点不会对链表的构成产生任何影响,也不会被包括在最终的链表结构中。空节点的存在主要是作为递归遍历的终止条件,帮助函数在适当的时候停止递归,确保只有有效的非空节点被处理并加入到链表中。

相关问题