将二叉树展平到链表(java)\为什么这个递归代码不起作用?

yqyhoc1h  于 2021-07-06  发布在  Java
关注(0)|答案(2)|浏览(317)

leetcode问题如下:
描述将二叉树展平为假“链表”进行预排序遍历。这里我们使用treenode中的右指针作为listnode中的下一个指针。
输入:{1,2,5,3,4,#,6}
输出:{1,#,2,#,3,#,4,#,5,#,6}
说明:

1
    / \
   2   5
  / \   \
 3   4   6

1
\
 2
  \
   3
    \
     4
      \
       5
        \
         6

下面的代码未返回预期值,但无法找出原因:

public class Solution {

    public void flatten (TreeNode root){
       TreeNode lastNode = null;
       helper (root, lastNode); 
    }

    private void helper(TreeNode root, TreeNode lastNode){
        if (root == null){
            return; 
        }

        if(lastNode != null){
            lastNode.left = null; 
            lastNode.right = root; 
        }
        lastNode = root; 
        TreeNode right = root.right;
        helper(root.left, lastNode); 
        helper(right, lastNode); 

    }
}

测试结果:输入{1,2,5,3,4,#,6}输出{1,#,5,#,6}期望{1,#,2,#,3,#,4,#,5,#,6}
无法理解为什么输出将是{1,ţ,5,ţ,6},而不是预期的{1,ţ,2,ţ,3,ţ,4,ţ,5,ţ,6}。有人能解释一下吗?谢谢

x7yiwoj4

x7yiwoj41#

private void helper(TreeNode root, TreeNode lastNode){
        if (root == null){
            return; 
        }

        if(lastNode != null){
            lastNode.left = null; //***1
            lastNode.right = root; //***1 
        }
        lastNode = root; 
        TreeNode right = root.right;
        helper(root.left, lastNode); //***2
        helper(right, lastNode); //***3
    }

在第1节中,将左子节点附加到此最后一个节点的右侧。在第2节中,您调用左边的子级,其中第1节将被执行。在第3节中,您将调用正确的子级,其中将执行第1节。
因此,当第2节完成它的工作时,通过调用第1节,lastnode将已经有了正确的子级。当调用第3节并执行自己的代码第1节时,它将覆盖第2节中完成的工作。
您可能想做的是在helper函数中返回“leaf”,并使用leaf作为lastnode(即node 4,而不是root)。

private TreeNode helper(TreeNode root, TreeNode leaf){
        if (root != null){
            if (leaf != null){
                leaf.left = null; //***1
                leaf.right = root; //***1 
            }
            leaf = root;
            TreeNode right = root.right;
            leaf = helper(root.left, leaf); //***2
            leaf = helper(right, leaf); //***3
        }

        return leaf; 
    }
41zrol4v

41zrol4v2#

你几乎把它编好了,但是有一个小错误。在编写代码时,您假设 lastNode 在按预定顺序访问时更新到最后一个节点。但事实并非如此。
这个 lastNode 在递归调用返回此行之后,变量仍然指向当前的最后一个节点 helper(right, lastNode); .
让我们举个例子。假设我们在节点2,那么我们改变 lastNode 到节点2,然后调用其左子节点。之后 helper(root.left, lastNode); 我们相信 lastNode 应该指向节点3。但事实并非如此,它仍然指向节点2。
让我们看看调试器在上面的场景中是怎么说的

我们应该做些什么来删除这个bug,只需在递归调用期间返回lastnode。
请参见下面的示例代码

private TreeNode helper(TreeNode root, TreeNode lastNode){
        if (root == null){
            return lastNode;
        }

        if(lastNode != null){
            lastNode.left = null;
            lastNode.right = root;
        }
        lastNode = root;
        TreeNode right = root.right;
        lastNode =  helper(root.left, lastNode);
        lastNode =  helper(right, lastNode);
        return lastNode;
}

经过上述更改后,结果是这样的

相关问题