面试经典算法系列之二叉树10 -- 二叉树展开为链表

面试经典算法25 - 二叉树展开为链表

LeetCode.114
公众号:阿Q技术站

问题描述

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

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

示例 1:

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

示例 2:

输入:root = []
输出:[]

示例 3:

输入:root = [0]
输出:[0]

提示:

  • 树中结点数在范围 [0, 2000]
  • -100 <= Node.val <= 100

思路

递归
  1. 对于每个节点,如果其左子节点不为空,则将其左子节点和右子节点分别展开成单链表。
  2. 将左子节点展开后的单链表接到根节点的右子节点位置。
  3. 将右子节点展开后的单链表接到左子节点展开后的单链表的最后一个节点的右子节点位置。
非递归
  1. 将左子树插入到右子树的地方。
  2. 将原来的右子树接到左子树的最右边节点。
  3. 考虑新的右子树的根节点,重复上述步骤,直到所有节点都被展开。

具体步骤如下:

  1. 对于当前节点 node,如果其左子节点不为空,则将其左子节点插入到右子节点的位置,然后将左子节点设为 nullptr
  2. 将原来的右子节点接到当前右子节点的最右边节点的右子节点。
  3. 将当前节点移动到其右子节点,重复步骤1和2,直到当前节点为空。

图解

  1. 从根节点root开始,遍历二叉树的每个节点curr。

  1. 如果当前节点curr的左节点不为空,找到左子树的最右边节点leftRightMost

  1. 将当前节点 curr 的右子节点接到 leftRightMost 的右子节点。

  1. 将当前节点 curr 的左子节点插入到当前节点 curr 的右子节点位置,将当前节点 curr 的左子节点置空。

  1. 将当前节点 curr 移动到其右子节点。

  1. 将当前节点 curr 的左子节点插入到当前节点 curr 的右子节点位置,将当前节点 curr 的左子节点置空。

  1. 将原来的右子树接到左子树的最右边节点

参考代码

C++
递归
#include <iostream>

using namespace std;

// 二叉树节点的定义
struct TreeNode {
    int val;
    TreeNode* left;
    TreeNode* right;
    TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};

void flatten(TreeNode* root) {
    if (!root) return;
    flatten(root->left);  // 展开左子树
    flatten(root->right); // 展开右子树
    TreeNode* left = root->left;
    TreeNode* right = root->right;
    root->left = nullptr;
    root->right = left;
    TreeNode* curr = root;
    while (curr->right) {
        curr = curr->right;
    }
    curr->right = right;
}

// 打印展开后的链表
void printList(TreeNode* root) {
    while (root) {
        cout << root->val << " ";
        root = root->right;
    }
    cout << endl;
}

// 创建二叉树
TreeNode* createTree(vector<int>& nodes, int index) {
    if (index >= nodes.size() || nodes[index] == -1) {
        return nullptr; // 如果节点为空,则返回nullptr
    }
    TreeNode* root = new TreeNode(nodes[index]); // 创建当前节点
    root->left = createTree(nodes, 2 * index + 1); // 创建左子树
    root->right = createTree(nodes, 2 * index + 2); // 创建右子树
    return root; // 返回当前节点
}

int main() {
    vector<int> nodes = {1, 2, 5, 3, 4, -1, 6}; // 二叉树的先序遍历序列
    TreeNode* root = createTree(nodes, 0); // 创建二叉树
    flatten(root); // 展开为单链表
    printList(root); // 打印展开后的链表

    return 0;
}
非递归
#include <iostream>

using namespace std;

// 二叉树节点的定义
struct TreeNode {
    int val;
    TreeNode* left;
    TreeNode* right;
    TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};

void flatten(TreeNode* root) {
    TreeNode* curr = root;
    while (curr) {
        if (curr->left) {
            // 找到左子树的最右边节点
            TreeNode* leftRightMost = curr->left;
            while (leftRightMost->right) {
                leftRightMost = leftRightMost->right;
            }
            // 将原右子树接到左子树最右边节点的右子节点
            leftRightMost->right = curr->right;
            // 将左子树插入到右子树的位置
            curr->right = curr->left;
            curr->left = nullptr;
        }
        // 移动到下一个节点
        curr = curr->right;
    }
}

// 打印展开后的链表
void printList(TreeNode* root) {
    while (root) {
        cout << root->val << " ";
        root = root->right;
    }
    cout << endl;
}

// 创建二叉树
TreeNode* createTree(vector<int>& nodes, int index) {
    if (index >= nodes.size() || nodes[index] == -1) {
        return nullptr; // 如果节点为空,则返回nullptr
    }
    TreeNode* root = new TreeNode(nodes[index]); // 创建当前节点
    root->left = createTree(nodes, 2 * index + 1); // 创建左子树
    root->right = createTree(nodes, 2 * index + 2); // 创建右子树
    return root; // 返回当前节点
}

int main() {
    vector<int> nodes = {1, 2, 5, 3, 4, -1, 6}; // 二叉树的先序遍历序列
    TreeNode* root = createTree(nodes, 0); // 创建二叉树
    flatten(root); // 展开为单链表
    printList(root); // 打印展开后的链表

    return 0;
}
Java
// 二叉树节点的定义
class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;
    TreeNode(int x) { val = x; }
}

class Solution {
    public void flatten(TreeNode root) {
        TreeNode curr = root;
        while (curr != null) {
            if (curr.left != null) {
                // 找到左子树的最右边节点
                TreeNode leftRightMost = curr.left;
                while (leftRightMost.right != null) {
                    leftRightMost = leftRightMost.right;
                }
                // 将原右子树接到左子树最右边节点的右子节点
                leftRightMost.right = curr.right;
                // 将左子树插入到右子树的位置
                curr.right = curr.left;
                curr.left = null;
            }
            // 移动到下一个节点
            curr = curr.right;
        }
    }

    // 测试函数
    public static void main(String[] args) {
        Solution solution = new Solution();
        // 创建二叉树
        TreeNode root = new TreeNode(1);
        root.left = new TreeNode(2);
        root.right = new TreeNode(5);
        root.left.left = new TreeNode(3);
        root.left.right = new TreeNode(4);
        root.right.right = new TreeNode(6);
        // 展开为单链表
        solution.flatten(root);
        // 打印展开后的链表
        TreeNode curr = root;
        while (curr != null) {
            System.out.print(curr.val + " ");
            curr = curr.right;
        }
        System.out.println();
    }
}
Python
# 二叉树节点的定义
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: TreeNode) -> None:
        curr = root
        while curr:
            if curr.left:
                # 找到左子树的最右边节点
                left_rightmost = curr.left
                while left_rightmost.right:
                    left_rightmost = left_rightmost.right
                # 将原右子树接到左子树最右边节点的右子节点
                left_rightmost.right = curr.right
                # 将左子树插入到右子树的位置
                curr.right = curr.left
                curr.left = None
            # 移动到下一个节点
            curr = curr.right

# 创建二叉树
def create_tree(nodes, index):
    if index >= len(nodes) or nodes[index] == -1:
        return None
    root = TreeNode(nodes[index])
    root.left = create_tree(nodes, 2 * index + 1)
    root.right = create_tree(nodes, 2 * index + 2)
    return root

# 打印展开后的链表
def print_list(root):
    while root:
        print(root.val, end=' ')
        root = root.right
    print()

# 测试代码
nodes = [1, 2, 5, 3, 4, -1, 6]
root = create_tree(nodes, 0)
solution = Solution()
solution.flatten(root)
print_list(root)
  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值