解题思路
114. 二叉树展开为链表
思路一:先序遍历
根据题目要求:展开后的单链表应该与二叉树 先序遍历 顺序相同。所以可以考虑使用先序遍历出来二叉树中的每一个节点进行处理:把每一个节点的左子树移动到右边作为新的右子树,然后把左子树清空,接着把原来的右子树嫁接到新的左子树的最右边的节点后(因为按照先序遍历的顺序,左边的节点都遍历完才轮到右边的节点)。
思路二:后序遍历
使用后序遍历:右,左,根的方式进行遍历。这样的话会发现遍历结束后的节点顺序和题目的要求刚好是相反的,所有要进行这样的处理:每遍历一个节点就把上次遍历的节点放到该节点的右节点处,同时左节点置null,因为是后序遍历,左节点置0不会影响后面节点的遍历处理。
代码
方法一:先序遍历
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
//运行时间:0ms , 内存消耗:38.1ms
//先序遍历:递归算法
public void flatten(TreeNode root) {
if(root == null) return;
if(root.left!=null){
TreeNode oldRight = root.right; //保留旧的右子树
root.right = root.left; //把左子树放到右边,替换掉右子树
root.left = null; //把左子树清空
//把旧的右子树放到原来左子树的最右边的节点的右边
TreeNode curr_node = root;
while(curr_node.right!=null){
curr_node = curr_node.right;
}
curr_node.right = oldRight;
}
// flatten(root.left);//因为前面操作就会把左子树换到右边,然后把左边清空,所有不需要这一步
flatten(root.right);
}
}
方法二:后序遍历
//运行时间:0ms , 内存消耗:38ms
private TreeNode pre_node; //上次所遍历到的节点
public void flatten(TreeNode root) {
if(root == null) return;
flatten(root.right);
flatten(root.left);
if(pre_node!=null){
root.right = pre_node;
root.left = null;
}
pre_node = root;
}