LeetCode LCR 052. 递增顺序搜索树
题目描述


题意分析
把二叉搜索树按中序顺序重排成一条右链:最左节点成为新根,每个节点的左孩子为空,右孩子指向下一个节点。BST 的中序序列已经有序,因此按访问顺序串接即可,无需重新排序。
解法:迭代中序原地串接
核心思路
[!blue]
用显式栈进行中序遍历:从
cur一路向左压栈,走到空后弹出一个节点,此时它的左子树已经处理完,可以访问它;随后转到它的右子树,重复同样过程。
head保存结果头,tail保存最后一个已接入的节点。第一次弹出的节点是中序首项,令它成为head;以后每弹出一个节点,就令tail.right指向它,再更新tail。这样所有已处理节点始终按中序顺序连接。访问当前节点后将它的左指针清空,因为那棵左子树已经遍历并接入结果,不再依赖这个旧连接。当前节点原来的右指针仍然保留,立即用
cur=cur.right进入未处理的右子树;等下一次串接改写旧尾节点的右指针时,遍历已经通过cur或栈保存了所需引用,不会丢失节点。每个节点恰好弹栈一次,也就恰好接入结果一次。最后一个节点是最右节点,其原右孩子本来就为空,所以遍历结束时得到一条完整的有序右链。
解题步骤
- 初始化空栈、空的
head与tail,令cur=root。- 当
cur非空或栈非空时,先把当前子树的左链全部压栈。- 弹出节点:首次访问时设置头节点,否则接到
tail.right。- 更新尾节点,清空当前节点的左指针,再转向其原右子树。
- 当前节点和栈都为空时返回
head。循环必须同时检查当前节点和栈:前者表示刚进入的子树,后者保存尚待访问的祖先。单节点树、纯左链和纯右链都按同样的中序规则处理;整个过程复用原节点,会修改原树结构。
代码实现
class Solution {
public TreeNode increasingBST(TreeNode root) {
TreeNode head = null;
TreeNode tail = null;
Deque<TreeNode> stack = new ArrayDeque<>();
TreeNode cur = root;
while (!stack.isEmpty() || cur != null) {
while (cur != null) {
stack.push(cur);
cur = cur.left;
}
cur = stack.pop();
if (head == null) {
head = cur;
} else {
tail.right = cur;
}
tail = cur;
cur.left = null;
cur = cur.right;
}
return head;
}
}
func increasingBST(root *TreeNode) *TreeNode {
var head, tail *TreeNode
stack := make([]*TreeNode, 0)
cur := root
for len(stack) > 0 || cur != nil {
for cur != nil {
stack = append(stack, cur)
cur = cur.Left
}
cur = stack[len(stack)-1]
stack = stack[:len(stack)-1]
if head == nil {
head = cur
} else {
tail.Right = cur
}
tail = cur
cur.Left = nil
cur = cur.Right
}
return head
}
复杂度分析
- 时间复杂度:$O(n)$,每个节点入栈、出栈和串接各一次。
- 空间复杂度:$O(h)$,显式栈保存待处理祖先,$h$ 为树高;不创建新的树节点。
关键点总结
[!green]
- 中序顺序决定新链顺序,
head和tail分别负责保留结果入口和追加节点。- 左子树处理完后才能清空左指针,原右子树则要先交给遍历继续处理。
- 原地重连复用节点,但仍需要栈保存尚未访问的祖先。
易错点总结
[!yellow]
- 按中序顺序接入节点,并把每个节点的 left 清空。
- 保留独立的 head 与 tail,移动尾指针时不能丢失结果头。
- 循环同时考虑当前节点与待处理栈;弹出节点后还要遍历其原右子树。
相似题目
| 题目 | 难度 | 关联与区别 |
|---|---|---|
| 114. 二叉树展开为链表 | 中等 | 同样原地连成链,本题按BST中序成为递增右链,原题按前序展开普通二叉树。 |
| 426. 将二叉搜索树转化为排序的双向链表 | 中等 | 同样按BST中序重连节点,原题连接为循环双向链表,本题只保留向右的单链。 |
转载与许可
许可
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处!