剑指offer26_二叉搜索树与双向链表_题解

二叉搜索树与双向链表

题目描述

输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。

分析

方案一:递归转换二叉树

将原先指向左子节点的指针调整为链表中指向前一个节点的指针,原先指向右子节点的指针调整为链表中指向后一个节点的指针。

递归把左右子树分别转换成排序双向链表,再和根节点链接起来。

/**
时间复杂度:O(N)
N 为二叉树的节点数,中序遍历需要访问所有节点。
空间复杂度:O(N)
最差情况下,即树退化为链表时,递归深度达到 N,系统使用 O(N) 栈空间。
**/
class Solution
{
public:
    TreeNode *tail = nullptr, *head = nullptr;
    void dfs(TreeNode *cur)
    {
        if (!cur)
            return;
        dfs(cur->left);
        //tail用于记录双向链表的尾结点
        if (tail)
            tail->right = cur;
        //当tail==null时,cur左侧没有节点,即此时cur为双向链表中的头节点
        else
            head = cur;
        cur->left = tail;
        //更新tail=cur
        tail = cur;
        dfs(cur->right);
    }
    TreeNode *Convert(TreeNode *root)
    {
        if (!root)
            return nullptr;
        dfs(root);
        return head;
    }
};

方法二:递归+数组

  • 中序遍历一遍二叉搜索树,将节点保存在一个数组中。
  • 遍历数组,更改每个节点的 \(left\)\(right\)
  • 返回数组第一个元素
/**
时间复杂度:O(N)
N 为二叉树的节点数,中序遍历需要访问所有节点。
空间复杂度:O(N)
保存节点的数组空间为O(N)
**/
class Solution
{
public:
    //中序遍历
    void inOrder(TreeNode *root, vector<TreeNode *> &nodes)
    {
        if (root == NULL)
        {
            return;
        }
        inOrder(root->left, nodes);
        nodes.emplace_back(root);
        inOrder(root->right, nodes);
    }
    TreeNode *Convert(TreeNode *root)
    {
        if (!root)
            return NULL;
        //nodes中保存了中序遍历的结果
        vector<TreeNode *> nodes;
        inOrder(root, nodes);
        for (int i = 0; i < nodes.size() - 1; i++)
        {
            nodes[i]->right = nodes[i + 1];
            nodes[i + 1]->left = nodes[i];
        }
        return nodes[0];
    }
};
posted @ 2020-12-26 22:35  RiverCold  阅读(63)  评论(0编辑  收藏  举报