题目:
Given a binary tree, flatten it to a linked list in-place.
For example,
Given
1 / \ 2 5 / \ \ 3 4 6
The flattened tree should look like:
1 \ 2 \ 3 \ 4 \ 5 \ 6
click to show hints.
If you notice carefully in the flattened tree, each node's right child points to the next node of a pre-order traversal.
Answer 1: 递归法
思路:观察题目转换的过程,我们按照前序遍历的顺序连接成一个链表,不过链表还是用树的结构,就是一直往右走(没有做孩子)来模拟链表。为了保证节点之间的链接,我们维护先序遍历的前一个节点pre, 然后每次把pre的左结点置空,右结点设为当前节点(即按照先序遍历顺序)。这里我们需要注意,还需维护右孩子节点savedRight,以方便等会进行递归。否则有可能当前节点的右结点可能被覆盖,后面就取不到了。
树的递归方法,我们主要就是考虑好递归结束条件和递归条件,如果递归会对树的结构进行修改的话,我们就需要保存一下结点。
Attention:
1. 维护两个节点,一个先序遍历前一个节点pre, 一个当前节点的右孩子节点savedRight。方便链接和保护右孩子节点。
private: TreeNode* pre = NULL; //维护一个上次访问的结点,需要将这次的结点连到pre上
TreeNode* savedRight = root->right;2. 注意链接过程,我们是把pre的左孩子置空,右孩子设为当前结点,实现前序链表链接。
if(pre != NULL) { pre->left = NULL; //上次结点左子树置为空 pre->right = root; //上次遍历结点右结点为root }
3. 注意前序遍历顺序,先是root->left递归,接下来是维护的右结点递归savedRight. 始终维护pre。
pre = root; flatten(root->left); flatten(savedRight); //改变了树的结构,从保存的树的根右结点继续遍历复杂度:O(N)
/** * Definition for binary tree * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ class Solution { public: void flatten(TreeNode *root) { if(root == NULL) return; TreeNode* savedRight = root->right; if(pre != NULL) { pre->left = NULL; //上次结点左子树置为空 pre->right = root; //上次遍历结点右结点为root } pre = root; flatten(root->left); flatten(savedRight); //改变了树的结构,从保存的树的根右结点继续遍历 } private: TreeNode* pre = NULL; //维护一个上次访问的结点,需要将这次的结点连到pre上 };
思路:
[解题思路]
1 \
2
/ \
3 4
\ 5 \ 6
对root的左子树进行处理,将左子树的根结点和左子树的右子树插入右子树中。接下来再对结点2进行处理,同样将2的左子树插入右子树中。我们通过访问结点2(根节点的左孩子)的最右结点(左子树最上一层的最右结点,最后被访问),得到了先序遍历左子树的最后一个节点(节点4),插入到根结点的右孩子(结点5)的前一个节点(节点4)。不断进行这个插入过程。
Attention:
1. 找到右子树的前一个节点,就是根结点的左孩子的最右结点。
TreeNode* ptr = root->left; while(ptr->right) ptr = ptr->right;2. 注意如何插入的过程。结合图记忆
ptr->right = root->right; root->right = root->left; root->left = NULL;3. 置root为root的右孩子,继续插入过程,知道root为NULL, 即root遍历到树的最后一个节点。
AC Code:
/** * Definition for binary tree * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ class Solution { public: void flatten(TreeNode *root) { while(root) { if(root->left) { TreeNode* ptr = root->left; while(ptr->right) ptr = ptr->right; ptr->right = root->right; root->right = root->left; root->left = NULL; } root = root->right; } } };