剑指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];
}
};