題目:
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
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)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) {
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上
};
Answer 2: 非遞歸方法
思路:
[解題思路]
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;
}
}
};