114. 二叉树展开为链表
给定一个二叉树,原地将它展开为链表。
Solution1:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
|
class Solution { public: void flatten(TreeNode* root) { if(!root) return; dfs(root); } TreeNode* dfs(TreeNode* node){ if(!node->left && !node->right) return node; TreeNode* lastLeft = NULL; TreeNode* lastRight = NULL; if(node->left){ lastLeft = dfs(node->left); } if(node->right){ lastRight = dfs(node->right); } if(lastLeft){ lastLeft->right = node->right; node->right = node->left; node->left = NULL; } if(lastRight) return lastRight; else return lastLeft; } };
|
思路:
从叶子结点开始,向上展开。每到一层,分别获得左子树和右子树的最后节点,将左子树的最后节点与当前节点的右子树的开始节点连接,将当前节点的右节点指向左子树的开始节点,左子树置空。
接着返回当前子树的最后节点,作为上一层的相应结点做相应的处理。
优化:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| class Solution { public: void flatten(TreeNode* root) { dfs(root); } TreeNode* dfs(TreeNode* node){ if(!node) return NULL; TreeNode* lastLeft; TreeNode* lastRight; lastLeft = dfs(node->left); lastRight = dfs(node->right); if(lastLeft){ lastLeft->right = node->right; node->right = node->left; node->left = NULL; } return lastRight ? lastRight : lastLeft ? lastLeft : node ; } };
|
将空节点做一般化考虑,在返回的时候做相应的处理。
分几种情况:
Solution2(终极版):
1 2 3 4 5 6 7 8 9 10 11 12
| class Solution { public: TreeNode* prev = NULL; void flatten(TreeNode* root) { if(!root) return; flatten(root->right); flatten(root->left); root->right = prev; root->left = NULL; prev = root; } };
|
看到评论区大神写的这段代码,我觉得我被虐的体无完肤。
首先,设置一个全局变量,该变量用来记录已经翻转过的开始结点。
接着,递归是首先下到最右边,从最右边开始的,这就保证了只需要关心已经展开链表的头结点,尾结点没必要再关心了。每次到达一个子树,从最右的结点开始,每个节点接到全局变量上。全局变量刷新为新的展开链表的头。如此一直到达根节点。