二叉树展开为链表C++
给你二叉树的根结点 root ,请你将它展开为一个单链表:
展开后的单链表应该同样使用 TreeNode ,其中 right 子指针指向链表中下一个结点,而左子指针始终为 null 。
展开后的单链表应该与二叉树 先序遍历 顺序相同。
迭代法,创建了一个哨兵节点(先序遍历),用了栈,空间复杂度为O(n)
class Solution {
public:void flatten(TreeNode* root) {if(root==nullptr) return;TreeNode* dummy = new TreeNode();stack<TreeNode*> st;st.push(root);while(!st.empty()){TreeNode* node = st.top();st.pop();// 栈先进后出,所以左子节点先出栈if(node->right) st.push(node->right);if(node->left) st.push(node->left);// 清空当前节点的左右子节点node->left = nullptr;node->right = nullptr;// 将当前节点加入新的链表dummy->right = node;dummy = node;}}
};
迭代法,原地创建,没有创建新节点,并且空间复杂度为O(1)
class Solution {
public:void flatten(TreeNode* root) {if(root==nullptr) return ;TreeNode* cur = root;while(cur){// 若当前节点的左子树存在,则检查左子树if(cur->left){// 找到左子树的“前驱节点”,即当前节点左子树的最右节点TreeNode* pre = cur->left;while(pre->right){pre=pre->right;}// 找到前驱节点后,将当前节点的右子树,挪到前驱节点的右子树中pre->right = cur->right;// 将当前节点的左子树,改到右子树中去,并置空左子树cur->right = cur->left;cur->left = nullptr;}// 若左子树不存在或左子树已变为右子树,则查看的下一个节点为右子树cur = cur->right;}}
};
思路:
- 找到左子树的最右节点(前驱节点)
- 将当前节点的右子树接到前驱节点的右边
- 将左子树移到右边,并置空左指针
1/ \2 5/ \ \
3 4 6
- 当前节点 1,左子树存在
– 找到左子树最右节点 (4)
– 将 1 的右子树 (5->6) 接到 4 的右边
– 将左子树移到右边
1\2/ \3 4 \5\6
以此类推