Easy
题目描述
给你一个二叉搜索树的根节点 root,请你将其重新排列为一个递增顺序查找树,使树中最左边的节点成为树的根节点,并且每个节点没有左子节点,只有一个右子节点。
示例 1:
输入:root = [5,3,6,2,4,null,8,1,null,null,null,7,9]
输出:[1,null,2,null,3,null,4,null,5,null,6,null,7,null,8,null,9]
示例 2:
输入:root = [5,1,7]
输出:[1,null,5,null,7]
提示:
- 给定树中的节点数介于
[1, 100]之间。 0 <= Node.val <= 1000
解题思路
这道题要求将二叉搜索树重新排列成只有右子树的递增链表结构。
核心思路:利用二叉搜索树的中序遍历性质,中序遍历的结果就是递增序列。我们可以通过中序遍历,将节点按顺序连接成只有右子树的链表。
主要解法:
- 中序遍历 + 重新构造:先中序遍历收集所有节点值,再构造新的链表结构
- 原地修改(推荐):在中序遍历过程中直接修改树结构,使用一个指针记录当前链表的尾节点
推荐解法详解: 使用原地修改的方法,在中序遍历过程中:
- 维护一个
prev指针,指向当前已构造链表的最后一个节点 - 对于每个访问的节点,将其左子树置空,让
prev的右子树指向当前节点 - 更新
prev为当前节点 - 使用虚拟头节点简化边界处理
这种方法时间复杂度O(n),空间复杂度O(h)(递归栈深度)。
代码实现
class Solution {
public:
TreeNode* increasingBST(TreeNode* root) {
TreeNode dummy(0);
prev = &dummy;
inorder(root);
return dummy.right;
}
private:
TreeNode* prev;
void inorder(TreeNode* node) {
if (!node) return;
inorder(node->left);
node->left = nullptr;
prev->right = node;
prev = node;
inorder(node->right);
}
};
class Solution:
def increasingBST(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
def inorder(node):
if not node:
return
inorder(node.left)
node.left = None
self.prev.right = node
self.prev = node
inorder(node.right)
dummy = TreeNode(0)
self.prev = dummy
inorder(root)
return dummy.right
public class Solution {
private TreeNode prev;
public TreeNode IncreasingBST(TreeNode root) {
TreeNode dummy = new TreeNode(0);
prev = dummy;
Inorder(root);
return dummy.right;
}
private void Inorder(TreeNode node) {
if (node == null) return;
Inorder(node.left);
node.left = null;
prev.right = node;
prev = node;
Inorder(node.right);
}
}
var increasingBST = function(root) {
let prev;
function inorder(node) {
if (!node) return;
inorder(node.left);
node.left = null;
prev.right = node;
prev = node;
inorder(node.right);
}
const dummy = new TreeNode(0);
prev = dummy;
inorder(root);
return dummy.right;
};
复杂度分析
| 复杂度类型 | 复杂度 | 说明 |
|---|---|---|
| 时间复杂度 | O(n) | 需要访问树中的每个节点一次 |
| 空间复杂度 | O(h) | 递归栈的深度,h为树的高度,最坏情况下O(n) |