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

时间:2018-10-02 07:15:32

标签: java algorithm recursion tree binary-tree

Here is a photo 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;
    }
}

有人可以引导我解决问题和所有递归调用吗?现在,我不了解该解决方案如何构建树节点。我目前正在解决这样的问题。

  1. constructMaximumBinaryTree(int [] nums)

  2. int maxIndex = getMaxIndex(nums,0,5)因此maxIndex =3。

  3. TreeNode根=6。

  4. root.left = helper(nums,0,2),因此maxIndex = 0。

  5. TreeNode根=3。

  6. root.left = helper(nums,0,-1),将触发基本情况并返回null。

在第6步之后迷路了。在第6步返回null之后,我是否要继续使用root.right = helper(nums,maxIndex + 1,high)?如果是这样,maxIndex和high将是什么?下一步是什么?

3 个答案:

答案 0 :(得分:1)

通常,递归方法将一个问题分解为多个子问题,并通过组合其解决方案来构建原始问题的解决方案。这恰好是在这种情况下发生的事情。

最大树的定义本身是递归的,这使得更容易理解解决方案。请注意,在定义的第2步和第3步中,我们需要从原始数组的子数组构造一个最大的子树。因此,我们用更少的输入元素即可解决相同的问题。

函数helper是此解决方案的关键-它从原始输入数组的连续子数组构造最大树。为了更好地理解该解决方案,首先请忽略具体的实现,并假设它只是-nums参数始终是原始输入数组,lowhigh以及first和the的索引子数组中的最后一个元素(包括两端)。 helper返回为提供的子数组构造的最大树的根。因此,对整个数组调用帮助将解决原始问题。

类似地,getMaxIndex接受原始数组的子数组(以相同的方式指定),并返回该子数组中具有最大值的元素的索引。根据最大树的定义,这将是新树中根元素的索引,以及我们应该在其中拆分左右子树的数组的索引(定义的第1点)。

现在,如果您知道这是这两个函数的工作,那么应该很容易理解它们中的逻辑。

答案 1 :(得分:1)

简短的回答是,您将移至root.right = helper(nums,maxIndex + 1,high),其中maxIndex = 0且high = 2,因此root.right = helper(nums,1,2)。

步骤将是:

  1. constructMaximumBinaryTree(int [] nums)
  2. int maxIndex = getMaxIndex(nums,0,5)因此maxIndex = 3。
  3. TreeNode根= 6。
  4. root.left = helper(nums,0,2),因此maxIndex = 0。
  5. TreeNode根= 3。
  6. root.left = helper(nums,0,-1),将触发基本情况并返回null。
  7. 我们继续处理root = 3的右子树,所以root.right = helper(nums,1,2),maxIndex = 1。
  8. TreeNode根= 2。
  9. root.left = helper(nums,1,0),将触发基本情况并返回null。
  10. 我们继续使用root = 2的右子树,所以root.right = helper(nums,2,2),maxIndex = 2。
  11. TreeNode根= 1。
  12. 现在左右都返回null,然后返回root = 6的右边子树。

答案 2 :(得分:1)

我经常发现,一些布局合理的打印语句对于理解算法流程非常有帮助,尤其是在涉及递归时。我已经更新了您的代码,以通过缩进字符串打印正在处理哪个子级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; 
}

根据您的输入,将产生:

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

我认为这使树的结构更加清晰。