LeetCode114—Flatten Binary Tree to Linked List

LeetCode114—Flatten Binary Tree to Linked List

原题

Given a binary tree, flatten it to a linked list in-place.

For example,
Given

     1
    / \
   2   5
  / \   \
 3   4   6

The flattened tree should look like:
1
 \
  2
   \
    3
     \
      4
       \
        5
         \
          6

分析

最朴素的方法就是先序遍历把节点保存,然后在顺序构造不含左子树的树,网上看到有其他的方法,等学习研究了再更新。

代码

class Solution {
private:
    void dfs(TreeNode*root, vector<TreeNode*>&Nodes)
    {
        if (root == NULL)
            return;
        Nodes.push_back(root);
        dfs(root->left, Nodes);
        dfs(root->right, Nodes);
    }
public:
    void flatten(TreeNode* root) {
        if (root == NULL)
            return;
        vector<TreeNode*>Nodes;
        dfs(root, Nodes);
        int i;
        root->left = NULL;
        for (i = 0; i < Nodes.size() - 1; i++)
        {
            Nodes[i]->right = Nodes[i + 1];
            Nodes[i]->left = NULL;
        }
        Nodes[i]->right = NULL;
        root = Nodes[0];
    }
};
### LeetCode 114 Flatten Binary Tree to Linked List 的解法 #### 方法一:递归方法 通过递归的方式解决此问题,可以按照前序遍历的思想来处理。具体来说,对于当前节点 `root`,如果它有左子树,则需要将右子树移动到左子树的最右侧节点之后,然后再将整个左子树移到 `root.right` 上,并设置 `root.left = None`。 以下是基于递归的方法实现: ```python # Definition for a binary tree node. class TreeNode: def __init__(self, val=0, left=None, right=None): self.val = val self.left = left self.right = right def flatten(root: TreeNode) -> None: """ Do not return anything, modify root in-place instead. """ if not root: return # 将左右子树分别展平 flatten(root.left) flatten(root.right) # 记录原来的左右子树 left = root.left right = root.right # 把原来左子树接到右边 root.left = None root.right = left # 找到新右子树的最后一个节点 temp = root while temp.right: temp = temp.right # 接上原有的右子树部分 temp.right = right ``` 这种方法的时间复杂度为 O(n),其中 n 是二叉树中的节点数[^3]。 --- #### 方法二:迭代方法(Morris 遍历) 为了达到空间复杂度 O(1),可以通过 Morris 遍历来解决问题。该算法的核心思想是在不使用额外栈或队列的情况下完成前序遍历操作。 以下是基于 Morris 遍历的解决方案: ```python def flatten_morris(root: TreeNode) -> None: current = root while current: if current.left: # 寻找左子树中最右侧节点 pre = current.left while pre.right: pre = pre.right # 修改指针结构 pre.right = current.right current.right = current.left current.left = None # 移动到下一个节点 current = current.right ``` 这种做法同样能够满足题目要求,在原地修改二叉树的同时保持时间复杂度为 O(n)[^2] 和空间复杂度为 O(1)[^2]。 --- #### 方法三:辅助列表存储节点 另一种较为直观的做法是利用一个临时数组保存前序遍历的结果,再依次重新构建链表形式的二叉树。虽然这种方式的空间复杂度较高 (O(n)),但它更容易理解。 代码如下所示: ```python def flatten_list(root: TreeNode) -> None: preorderList = [] def dfs(node): if node: preorderList.append(node) dfs(node.left) dfs(node.right) dfs(root) size = len(preorderList) for i in range(1, size): prev, curr = preorderList[i - 1], preorderList[i] prev.left = None prev.right = curr ``` 尽管上述方法易于编写和调试,但由于其较高的内存消耗,通常不如其他两种方式更优[^4]。 --- ### 性能比较 | **方法** | **时间复杂度** | **空间复杂度** | |------------------|---------------|---------------| | 递归 | O(n) | O(h), h 表示树的高度 | | 迭代(Morris) | O(n) | O(1) | | 辅助列表 | O(n) | O(n) | 推荐优先考虑迭代方法或者优化后的递归版本以减少不必要的开销。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值