简体   繁体   English

如何解决这个递归二叉树问题?

[英]How can I walk through this recursive binary tree problem?

这是问题的照片。

This is a working solution of the problem: 这是该问题的可行解决方案:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public TreeNode constructMaximumBinaryTree(int[] nums) {
        return helper(nums, 0, nums.length-1);
    }

    public TreeNode helper(int[] nums, int low, int high){
        if (high < low){ return null; }
        //find max element's index
        int maxIndex = getMaxIndex(nums, low, high);

        //construct root node
        TreeNode root = new TreeNode(nums[maxIndex]);

        //generate left subtree from the left part of subarray
        root.left = helper(nums, low, maxIndex-1);

        //generate right sub tree from the right part of subarray
        root.right = helper(nums, maxIndex+1, high);


        return root; 
    }

    public int getMaxIndex(int[] nums, int low, int high){
        int maxIndex = low;
        for (int i = low+1; i <= high; i++){
            if (nums[i] > nums[maxIndex]){
                maxIndex = i;
            }
        }
        return maxIndex;
    }
}

Can someone please walk me through the problem and all of the recursive calls? 有人可以指导我解决问题和所有递归调用吗? Right now I do not understand how the solution builds the tree node. 现在,我不了解该解决方案如何构建树节点。 I'm currently walking through the problem like this. 我目前正在解决这样的问题。

  1. constructMaximumBinaryTree(int[] nums) ConstructMaximumBinaryTree(int [] nums)

  2. int maxIndex = getMaxIndex(nums, 0, 5) so maxIndex = 3. int maxIndex = getMaxIndex(nums,0,5)所以maxIndex = 3。

  3. TreeNode root = 6. TreeNode根= 6。

  4. root.left = helper(nums, 0, 2) so maxIndex = 0. root.left = helper(nums,0,2)所以maxIndex = 0。

  5. TreeNode root = 3. TreeNode根= 3。

  6. root.left = helper(nums, 0, -1), which triggers the base case and returns null. root.left = helper(nums,0,-1),将触发基本情况并返回null。

I get lost after step 6. After step 6 returns null, do I move on to root.right = helper(nums, maxIndex+1, high)? 我在第6步之后迷路了。在第6步返回null之后,我是否要继续使用root.right = helper(nums,maxIndex + 1,high)? If so, what would maxIndex and high be? 如果是这样,maxIndex和high将是什么? And what are the next steps? 下一步是什么?

Typically a recursive approach breaks a problem into multiple sub problems and builds the solution of the original problem by combining their solutions. 通常,递归方法将一个问题分解为多个子问题,并通过组合其解决方案来构建原始问题的解决方案。 This is exactly what happens in this case too. 在这种情况下,也正是这种情况。

The fact that the definition of maximum tree is itself recursive makes it easier to understand the solution. 最大树的定义本身是递归的,这使得更容易理解解决方案。 Note that in steps 2 and 3 of the definition we need to construct a maximum sub tree from a sub array of the original array. 请注意,在定义的第2步和第3步中,我们需要从原始数组的子数组构造一个最大的子树。 Thus we solve the same problem with fewer input elements. 因此,我们用更少的输入元素解决了相同的问题。

The function helper is the key to this solution - it constructs a maximum tree from a contiguous subarray of the original input array. 函数helper是此解决方案的关键-它从原始输入数组的连续子数组构造最大树。 To understand the solution better first ignore the concrete implementation and assume that it does just that - nums parameter is always the original input array and low and high and the indices of the first and the last element in the sub array respectively (both inclusive). 为了更好地理解该解决方案,首先请忽略具体的实现,并假设它只是执行nums参数始终是原始输入数组,并且分别是lowhigh以及子数组中第一个元素和最后一个元素的索引(包括两端)。 helper returns the root of the maximum tree constructed for the provided sub array. helper返回为提供的子数组构造的最大树的根。 Thus calling help with the whole array will solve the original problem. 因此,对整个数组调用帮助将解决原始问题。

Similarly getMaxIndex takes a sub array of the original array (specified the same way) and returns the index of the element in that sub array that has maximum value. 同样, getMaxIndex接受原始数组的子数组(以相同的方式指定),并返回该子数组中具有最大值的元素的索引。 According to the definition of maximum tree this would be the index of the root element in the new tree and the index at which we should split the array for the left and right subtrees (point 1 of the definition). 根据最大树的定义,这将是新树中根元素的索引,以及我们应该在其中拆分左右子树的数组的索引(定义的第1点)。

Now if you know that this is what the two functions do it should be relatively easy to understand the logic in them. 现在,如果您知道这是这两个函数的工作,那么应该很容易理解它们中的逻辑。

The short answer is yes, you move to root.right = helper(nums, maxIndex+1, high), where maxIndex = 0 and high = 2, so root.right = helper(nums, 1, 2). 简短的答案是,您将移至root.right = helper(nums,maxIndex + 1,high),其中maxIndex = 0且high = 2,因此root.right = helper(nums,1,2)。

The steps would be: 步骤将是:

  1. constructMaximumBinaryTree(int[] nums) ConstructMaximumBinaryTree(int [] nums)
  2. int maxIndex = getMaxIndex(nums, 0, 5) so maxIndex = 3. int maxIndex = getMaxIndex(nums,0,5)所以maxIndex = 3。
  3. TreeNode root = 6. TreeNode根= 6。
  4. root.left = helper(nums, 0, 2) so maxIndex = 0. root.left = helper(nums,0,2)所以maxIndex = 0。
  5. TreeNode root = 3. TreeNode根= 3。
  6. root.left = helper(nums, 0, -1), which triggers the base case and returns null. root.left = helper(nums,0,-1),将触发基本情况并返回null。
  7. We proceed with the right subtree for root = 3, so root.right = helper(nums, 1, 2), with maxIndex = 1. 我们继续处理root = 3的右子树,所以root.right = helper(nums,1,2),maxIndex = 1。
  8. TreeNode root = 2. TreeNode根= 2。
  9. root.left = helper(nums, 1, 0), which triggers the base case and returns null. root.left = helper(nums,1,0),它将触发基本情况并返回null。
  10. We proceed with the right subtree for root = 2, so root.right = helper(nums, 2, 2), with maxIndex = 2. 我们继续处理root = 2的右子树,所以root.right = helper(nums,2,2),maxIndex = 2。
  11. TreeNode root = 1. TreeNode根= 1。
  12. Now both left and right return null, and we return to the right subtree of root = 6. 现在,左和右都返回null,然后返回root = 6的右子树。

I often it find that some well placed print statements can be extremely helpful in understanding the flow of an algorithm, especially when it involves recursion. 我经常发现,一些布局合理的打印语句对于理解算法流程特别有用,特别是在涉及递归时。 I've updated your code to print which child , L or R , is being processed and the level, via an indent string. 我已经更新了您的代码,以通过缩进字符串打印要处理的子级LR以及级别。

public TreeNode constructMaximumBinaryTree(int[] nums) {
  return helper(nums, 0, nums.length-1, "", "");
}

public TreeNode helper(int[] nums, int low, int high, String side, String ind){   
  if (high < low){ return null; }

  System.out.println(ind + side + Arrays.toString(Arrays.copyOfRange(nums, low, high+1)));

  //find max element's index
  int maxIndex = getMaxIndex(nums, low, high);

  //construct root node
  TreeNode root = new TreeNode(nums[maxIndex]);

  //generate left subtree from the left part of subarray
  root.left = helper(nums, low, maxIndex-1, "L", ind + "  ");

  //generate right sub tree from the right part of subarray
  root.right = helper(nums, maxIndex+1, high, "R", ind + "  ");

  return root; 
}

On your input this produces: 根据您的输入,将产生:

[3, 2, 1, 6, 0, 5]
  L[3, 2, 1]
    R[2, 1]
      R[1]
  R[0, 5]
    L[0]

Which I think makes the construction of the tree much clearer. 我认为这使树的结构更加清晰。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM