LeetCode114:二叉树展开为链表(三解法)

题目LeetCode114

给你二叉树的根结点 root ,请你将它展开为一个单链表:

  • 展开后的单链表应该同样使用 TreeNode ,其中 right 子指针指向链表中下一个结点,而左子指针始终为 null 。
  • 展开后的单链表应该与二叉树 先序遍历 顺序相同。

输入: root = 1,2,5,3,4,null,6
输出:1,null,2,null,3,null,4,null,5,null,6

Python解法

解法一(前序遍历)

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
class Solution:
    def flatten(self, root: Optional[TreeNode]) -> None:
        """
        Do not return anything, modify root in-place instead.
        """

        preorderList = list()

        def preorder(root: TreeNode):
            if root:
                preorderList.append(root)
                preorder(root.left)
                preorder(root.right)

        preorder(root)
        size = len(preorderList)

        for i in range(1, size):
            pre, cur = preorderList[i - 1], preorderList[i]
            pre.left = None
            pre.right = cur

解法二(遍历并生成)

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
class Solution:
    def flatten(self, root: Optional[TreeNode]) -> None:
        """
        Do not return anything, modify root in-place instead.
        """
        if not root:
            return
            
        stack = [root]
        pre = None

        while stack:

            cur = stack.pop()

            if pre:
                pre.left = None
                pre.right = cur

            left, right = cur.left, cur.right

            if right:
                stack.append(right)
            if left:
                stack.append(left)
            
            pre = cur

过程演示

解法三(前驱结点)

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
class Solution:
    def flatten(self, root: Optional[TreeNode]) -> None:
        """
        Do not return anything, modify root in-place instead.
        """

        cur = root

        while cur:

            if cur.left:
                predecessor = cur.left

                while predecessor:
                    predecessor = precedecessor.right

                predecessor.right = cur.right
                cur.right = cur.left
                cur.left = None

            cur = cur.right

过程演示

Java解法

解法一(前序遍历)

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 {
    // 存储前序遍历所有节点
    private List<TreeNode> preList = new ArrayList<>();

    public void flatten(TreeNode root) {
        // 1. 递归前序遍历收集节点
        preOrderTraverse(root);
        int size = preList.size();
        // 2. 遍历列表,拼接成单链表
        for (int i = 1; i < size; i++) {
            TreeNode prev = preList.get(i - 1);
            TreeNode curr = preList.get(i);
            prev.left = null;   // 左指针置空
            prev.right = curr;  // 右指针指向下一节点
        }
    }

    // 递归前序遍历:根 -> 左 -> 右
    private void preOrderTraverse(TreeNode root) {
        if (root == null) return;
        preList.add(root);
        preOrderTraverse(root.left);
        preOrderTraverse(root.right);
    }
}

解法二(遍历并生成)

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 {
    public void flatten(TreeNode root) {
        if (root == null) return;
        Stack<TreeNode> stack = new Stack<>();
        stack.push(root);
        TreeNode prev = null; // 记录上一个处理的节点

        while (!stack.isEmpty()) {
            TreeNode curr = stack.pop();
            // 上一节点指向当前节点
            if (prev != null) {
                prev.left = null;
                prev.right = curr;
            }
            // 先存左右子节点,栈后进先出,先压右再压左保证前序
            TreeNode left = curr.left;
            TreeNode right = curr.right;
            if (right != null) {
                stack.push(right);
            }
            if (left != null) {
                stack.push(left);
            }
            // 更新前驱节点
            prev = curr;
        }
    }
}

解法三(前驱结点)

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 {
    public void flatten(TreeNode root) {
        TreeNode curr = root;
        // 逐个向右遍历节点
        while (curr != null) {
            // 当前节点存在左子树才需要调整
            if (curr.left != null) {
                // nxt 保存左子树头部
                TreeNode nxt = curr.left;
                TreeNode predecessor = nxt;
                // 找到左子树最右侧节点
                while (predecessor.right != null) {
                    predecessor = predecessor.right;
                }
                // 左子树末尾接上原右子树
                predecessor.right = curr.right;
                // 左子树移到右侧,清空左指针
                curr.left = null;
                curr.right = nxt;
            }
            // 处理下一个节点
            curr = curr.right;
        }
    }
}

C++解法

解法一(前序遍历)

cpp 复制代码
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
private:
    vector<TreeNode*> preList;

    // 前序递归收集节点
    void preOrderTraverse(TreeNode* root) {
        if (!root) return;
        preList.push_back(root);
        preOrderTraverse(root->left);
        preOrderTraverse(root->right);
    }

public:
    void flatten(TreeNode* root) {
        preOrderTraverse(root);
        int size = preList.size();
        // 节点串联成右斜单链表
        for (int i = 1; i < size; ++i) {
            TreeNode* prev = preList[i - 1];
            TreeNode* curr = preList[i];
            prev->left = nullptr;
            prev->right = curr;
        }
    }
};

解法二(遍历并生成)

cpp 复制代码
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    void flatten(TreeNode* root) {
        if (!root) return;
        stack<TreeNode*> stk;
        stk.push(root);
        TreeNode* prev = nullptr;

        while (!stk.empty()) {
            TreeNode* curr = stk.top();
            stk.pop();

            // 拼接前后节点
            if (prev) {
                prev->left = nullptr;
                prev->right = curr;
            }

            // 先右后左入栈,弹出顺序为前序
            TreeNode* left = curr->left;
            TreeNode* right = curr->right;
            if (right) stk.push(right);
            if (left) stk.push(left);

            prev = curr;
        }
    }
};

解法三(前驱结点)

cpp 复制代码
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    void flatten(TreeNode* root) {
        TreeNode* curr = root;
        while (curr) {
            // 存在左子树则重构指针
            if (curr->left) {
                TreeNode* nxt = curr->left;
                TreeNode* predecessor = nxt;
                // 遍历到左子树最右端节点
                while (predecessor->right) {
                    predecessor = predecessor->right;
                }
                // 拼接原右子树
                predecessor->right = curr->right;
                // 左树迁移到右分支
                curr->left = nullptr;
                curr->right = nxt;
            }
            // 向右前进
            curr = curr->right;
        }
    }
};
相关推荐
m0_6399069411 小时前
Redis入门|五种数据结构、使用场景、持久化RDB&AOF
数据结构·数据库·redis
2601_9707038315 小时前
工业除湿机租赁:把一份租金合同拆开看
大数据·数据结构·算法·数据库架构·推荐算法
丘山望岳20 小时前
单调栈和单调队列
数据结构
UIU1141 天前
P16237 [蓝桥杯 2026 省 B] 应急布线
数据结构·c++·算法·蓝桥杯
黎相思1 天前
BTree
数据结构·b树·b+树
UIU1142 天前
P1233 [ICPC 2001 Taejon R] 木棍加工
数据结构·c++·算法·动态规划
niyongsheng2 天前
3D 装箱算法工程化:数据结构、放置启发式与支撑规则
数据结构·算法·rust
叉烧滑蛋2 天前
B站台湾大学郭彦甫|MATLAB 学习笔记|04 变量与档案存取
数据结构
j7~2 天前
【穷举、深搜与回溯算法】一棵决策树讲透全排列与子集
数据结构·c++·算法·leetcode·回溯·递归
not coder2 天前
一文讲通--从树到红黑树
数据结构·算法