leetcode----114.二叉树展开为链表(前序、后序三种解法)

114.二叉树展开为链表

问题:给你二叉树的根结点root,请你将它展开为一个单链表:

  • 展开后的单链表应该同样使用TreeNode,其中 right子指针指向链表中下一个结点,而左子指针始终为null
  • 展开后的单链表应该与二叉树 先序遍历 顺序相同。

思路:感觉涉及递归的问题,想起来都很抽象,最主要的明白递归函数的定义。

方法一:递归—后序

比如这道题flatten 函数的定义为:将以root为根的二叉树转化为链表(拉平)。

明白了定义之后,接下来就是利用这个定义实现将二叉树转化为链表。

  1. root的左右子树都拉平(递归函数的工作)
  2. root的右子树接到左子树下面,然后将整个左子树作为root的右子树。

这样就完成了对以root为根节点的二叉树的拉平。对于具体如何将root的左右子树拉平,就是递归函数flatten 的工作,我们只需要考虑,root的左右子树都已经拉平了,接下来应该怎么操作。

class Solution {
    public void flatten(TreeNode root) {
        if(root == null) return;
        
        flatten(root.left);
        flatten(root.right);

        TreeNode left = root.left;
        TreeNode right = root.right;

        root.left = null;
        root.right = left;

        TreeNode p = root;
        
        while(p.right != null){
            p = p.right;
        }

        p.right = right;
    }
}

方法二:递归----前序

如果在前序遍历时,交换当前节点的左右子树,会出现节点丢失的问题,所以可以先保存当前节点的左右孩子,然后使用头插法的方式建立链表,然后再这样将其左右孩子也转化为链表。

class Solution {
    private TreeNode pre = null;
    public void flatten(TreeNode root) {
        if(root == null) return;
        
        TreeNode l = root.left;
        TreeNode r = root.right;

        root.left = null;

        if(pre != null) {
            pre.right = root;
        }
        pre = root;

        flatten(l);
        flatten(r);
    }
}

方法三:非递归—前序

这道题最主要的一个点在于前序遍历中,当前节点左子树的最右节点为右子树的前驱节点

根据上面这个思路将这道题转化为寻找当前节点右子树的前驱节点。写法有些类似于Morris算法。对于当前节点cur有两种情况:

  • 当前节点的左孩子为空,此时当前节点右子树的前驱节点就是当前节点,则不做任何操作,继续遍历其右子树cur=cur.right
  • 若当前节点的左孩子不为空,此时需要进行以下操作
    • 首先寻找其左子树的最右节点作为当前节点cur右子树的前驱节点。即mostR.right=cur.right,mostR表示最右节点;
    • 然后将当前节点的左子树赋给其右子树,即cur.right=cur.left
    • 将当前节点的左子树置为null,继续遍历当前节点的左子树,即cur=cur.right,因为已经将左子树赋给右子树且将左子树置为null了,此时当前节点的右孩子就是原来的左孩子。
  • 直到遍历完整颗树。
class Solution {
    public void flatten(TreeNode root) {
        if(root == null) return;
        
        TreeNode cur = root;
        while(cur != null){
            if(cur.left != null){
                TreeNode mostR = cur.left;
                while(mostR.right != null){
                    mostR = mostR.right;
                }

                mostR.right = cur.right;
                cur.right = cur.left;
                cur.left = null;
            } 
            cur = cur.right;
        }
    }
}

你可能感兴趣的:(#,leetcode,链表,leetcode,数据结构,算法)