零、LeetCode 原题
一、题目描述
给你二叉树的根结点 root ,请你将它展开为一个单链表:
- 展开后的单链表应该同样使用 TreeNode ,其中 right 子指针指向链表中下一个结点,而左子指针始终为 null 。
- 展开后的单链表应该与二叉树 先序遍历 顺序相同。
进阶:你可以使用原地算法(O(1) 额外空间)展开这棵树吗?
二、测试用例
示例 1:
输入:root = [1,2,5,3,4,null,6]
输出:[1,null,2,null,3,null,4,null,5,null,6]
示例 2:
输入:root = []
输出:[]
示例 3:
输入:root = [0]
输出:[0]
提示:
树中结点数在范围 [0, 2000] 内
-100 <= Node.val <= 100
三、解题思路
3.1 栈
- 基本思路:
使用栈进行先序遍历,然后一个一个连接起来; - 具体思路:
- 根入栈;
- 只要栈非空:
- 弹出栈顶元素,将栈顶元素拼接到链表尾部;
- 只要右子树非空,将右子树压入栈;
- 只要左子树非空,将左子树压入栈;
3.2 找前驱(优化空间复杂度)
- 基本思路:
找到右子树的前驱,然后拼接到其后面;然后再将每个结点转为链表; - 具体思路:
- 遍历链表:
- 如果左子树非空,那么左子树最右节点就是右子树的前驱,
- 找到前驱并将右子树拼接到后面;
- 将左子树移动到右子树位置,左子树设置为空;
- 如果左子树为空,则右子树的前驱就是根,所以不做处理;
- 如果左子树非空,那么左子树最右节点就是右子树的前驱,
- 遍历链表:
四、参考代码
4.1 栈
时间复杂度: O ( n ) \Omicron(n) O(n)
空间复杂度: O ( h ) \Omicron(h) O(h)【 弹出一个元素,最多压入两个元素,而这样的情况只会发生在添加子树时,一但不添加子树,就只会弹出,所以最坏情况就是2倍的树高;如果树退化为线性,则h=n
】
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left),
* right(right) {}
* };
*/
class Solution {
public:
void flatten(TreeNode* root) {
if (!root)
return;
stack<TreeNode*> s;
TreeNode* head = new TreeNode();
s.push(root);
while (!s.empty()) {
TreeNode* p = s.top();
s.pop();
head->right = p;
head->left = nullptr;
head = head->right;
if (p->right) {
s.push(p->right);
}
if (p->left) {
s.push(p->left);
}
}
}
};
4.2 找前驱(优化空间复杂度)
时间复杂度: O ( n ) \Omicron(n) O(n)
空间复杂度: O ( 1 ) \Omicron(1) O(1)
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left),
* right(right) {}
* };
*/
class Solution {
public:
void flatten(TreeNode* root) {
if (!root)
return;
TreeNode* p = root;
while (p) {
TreeNode* q = p->left;
if (q) {
while (q->right) {
q = q->right;
}
q->right = p->right;
p->right = p->left;
p->left = nullptr;
}
p = p->right;
}
}
};