剑指 Offer(第2版)面试题 36:二叉搜索树与双向链表

剑指 Offer(第2版)面试题 36:二叉搜索树与双向链表

  • 剑指 Offer(第2版)面试题 36:二叉搜索树与双向链表
    • 解法1:中序遍历 - 递归
    • 解法2:中序遍历 - 迭代

剑指 Offer(第2版)面试题 36:二叉搜索树与双向链表

题目来源:49. 二叉搜索树与双向链表

解法1:中序遍历 - 递归

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

例如,输入下图中左边的二叉搜索树,则输出右边的排序双向链表。

剑指 Offer(第2版)面试题 36:二叉搜索树与双向链表_第1张图片

二叉搜索树(BST)具有这样的性质:其左子树上的节点的值都小于等于根节点的值,其右子树上的节点的值都大于等于根节点的值。

于是我们想到,中序遍历这个二叉搜索树。设置 pLastNodeInList 指针指向双向链表的末尾,指针 cur 指向当前处理的节点,先向 cur->left 递归下去, 将当前节点的 left 指向链表的队尾,队尾的 right 指向当前节点,然后当前节点变成新的队尾,即:

  1. cur->left = *pLastNodeInList。
  2. 若 *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 是二叉搜索树的节点个数。

你可能感兴趣的:(剑指,Offer,链表,数据结构,C++,剑指Offer,二叉树)