重点:
(1)前序遍历:存储前序遍历序列,然后建立新链表;迭代和递归两种实现;
(2)寻找前驱节点:空间复杂度O(1)。
难度中等
给你二叉树的根结点 root ,请你将它展开为一个单链表:
TreeNode ,其中 right 子指针指向链表中下一个结点,而左子指针始终为 null 。示例 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进阶:你可以使用原地算法(O(1) 额外空间)展开这棵树吗?
前序遍历之后,把节点顺序存储下来,然后建立链表即可。左指针指向nullptr,右指针指向下一个元素;
对于一个节点,如果其没有左子树,只有右子树,那么该节点就不需要展开操作。如果其有左子树,那么对于其右子树来说,左子树的最后一个节点被访问之后,该节点的右子树也即将被访问。这说明左子树的最后一个节点是右子树的前驱节点,也是该节点的前驱节点(因为是先序遍历)。那么问题转化为寻找前驱节点。
对于一个左子树非空的节点Anode,我们寻找其左子树C最后一个节点,就寻找其最右边的节点B。找到之后,将A的右子树连接到B的右子树Bnode->right=C,然后将左子树C连接到A的右子树Anode->right=C,然后Anode->left=nullptr。此时节点A只有右子树。那么寻找其右子树的第一个节点,进行再次操作。
- class Solution {
- public:
- void flatten(TreeNode* root) {
- vector
vec; - stack
stk; - while(!stk.empty()||root!=nullptr){
- while(root!=nullptr){
- stk.push(root);
- vec.push_back(root);
- root=root->left;
- }
- root=stk.top();
- stk.pop();
- root=root->right;
- }
- int size=vec.size();
- for(int i=1;i
- TreeNode *pre=vec.at(i-1),*cur=vec.at(i);
- pre->left=nullptr;
- pre->right=cur;
- }
- }
- };
- class Solution {
- public:
- void flatten(TreeNode* root) {
- TreeNode *cur=root;
- while(cur!=nullptr){
- if(cur->left!=nullptr){
- auto next=cur->left;//即将链接到cur的右子树
- auto pressdor=next;
- while(pressdor->right!=nullptr)
- pressdor=pressdor->right;
- pressdor->right=cur->right;
- cur->left=nullptr;
- cur->right=next;
- }
- cur=cur->right;
- }
- }
- };