剑指 Offer(第2版)面试题 36:二叉搜索树与双向链表
- 剑指 Offer(第2版)面试题 36:二叉搜索树与双向链表
- 解法1:中序遍历 - 递归
- 解法2:中序遍历 - 迭代
剑指 Offer(第2版)面试题 36:二叉搜索树与双向链表
题目来源:49. 二叉搜索树与双向链表
解法1:中序遍历 - 递归
题目要求输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。还要求不能创建任何新的结点,只能调整树中结点指针的指向。
例如,输入下图中左边的二叉搜索树,则输出右边的排序双向链表。
二叉搜索树(BST)具有这样的性质:其左子树上的节点的值都小于等于根节点的值,其右子树上的节点的值都大于等于根节点的值。
于是我们想到,中序遍历这个二叉搜索树。设置 pLastNodeInList 指针指向双向链表的末尾,指针 cur 指向当前处理的节点,先向 cur->left 递归下去, 将当前节点的 left 指向链表的队尾,队尾的 right 指向当前节点,然后当前节点变成新的队尾,即:
- cur->left = *pLastNodeInList。
- 若 *pLastNodeInList 不为空指针,则 (*pLastNodeInList)->right = cur。
最后向 cur->right 递归下去。
处理完成后,pLastNodeInList 指向双向链表的末尾,向左指针移动,直至双向链表的最左侧的节点,返回该节点。
代码:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution
{
public:
TreeNode *convert(TreeNode *root)
{
if (root == nullptr)
return nullptr;
// pLastNodeInList 指向双向链表的尾节点
TreeNode *pLastNodeInList = nullptr;
inOrderConvertNode(root, &pLastNodeInList);
// 找到双向链表的头节点
TreeNode *listHead = pLastNodeInList;
while (listHead && listHead->left)
listHead = listHead->left;
return listHead;
}
// 辅函数 - 中序遍历转换
void inOrderConvertNode(TreeNode *p, TreeNode **pLastNodeInList)
{
if (p == nullptr)
return;
TreeNode *cur = p;
if (cur->left)
inOrderConvertNode(cur->left, pLastNodeInList);
cur->left = *pLastNodeInList;
if (*pLastNodeInList)
(*pLastNodeInList)->right = cur;
*pLastNodeInList = cur;
if (cur->right)
inOrderConvertNode(cur->right, pLastNodeInList);
}
};
复杂度分析:
时间复杂度:O(n),其中 n 是二叉搜索树的节点个数。每个节点都会遍历一次。
空间复杂度:O(depth),其中 depth 是二叉搜索树的深度。
解法2:中序遍历 - 迭代
代码:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution
{
public:
static TreeNode *convert(TreeNode *root)
{
TreeNode *head = nullptr, *prev = nullptr;
stack<TreeNode *> stk;
while (root || !stk.empty())
{
while (root)
{
stk.push(root);
root = root->left;
}
root = stk.top();
stk.pop();
if (head)
{
prev->right = root;
root->left = prev;
}
else
{
head = root;
prev = root;
}
prev = root;
root = root->right;
}
return head;
}
};
复杂度分析:
时间复杂度:O(n),其中 n 是二叉搜索树的节点个数。
空间复杂度:O(n),其中 n 是二叉搜索树的节点个数。