这道题自己尝试着做了一下,感觉还是得用递归来做比较简单,但是一直想的是用前序遍历来构造链表,导致怎么做都不对,去看了下灵神的题解,然后问了下GPT,现在终于弄明白了。虽然构造出来的链表的排列顺序是按照前序遍历来排列的,但是在构造的时候不能用前序遍历,因为按照根 -> 左 -> 右的顺序遍历的话,我们需要将左孩子节点移到右孩子节点处,然后左孩子置空,这样右孩子就直接丢失了,就算我们用一个额外的变量来提前保存右子树也无法解决。考虑以下情况:
1/ \2 5/ \ \
3 4 6
处理节点 1 时,将 1 的左子树(2)移到右侧,原右子树(5)丢失。
即使保存 5 的引用,递归处理 2 的子树后,无法将 5 正确连接到 2 的右子树末尾。
所以我们需要从后往前构造,这样就当后面的节点处理完毕后,就不会有任何的遗留问题,专心处理前一个节点与当前节点的连接即可,感觉有点像python的列表从后往前删元素一样。为了保证构造出来的链表依旧按照根 -> 左 -> 右的顺序排列,我们需要按照右 -> 左 -> 根的顺序进行递归。
/*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}* };*/
class Solution {
public://虽然我们最终需要的链表顺序是先序遍历的结果,但直接使用前序遍历会破坏树的结构。//后序遍历的变形(右 - 左 - 根)通过逆向构建链表,巧妙地避免了这个问题,确保我们能够正确展开二叉树。TreeNode* pre = nullptr;void flatten(TreeNode* root) {//递归终止条件if(!root) return ;//右flatten(root -> right);//左flatten(root -> left);//根root -> left = nullptr;root -> right = pre;pre = root;}
};