力扣654题、105题、106题(二叉树、递归)

654、寻找最大二叉树

基本思想:

构造二叉树,根节点要做的就是想办法把自己构造出来,

先找到数组中的最大值,然后再用递归调用左右数组构造左右子树

前序遍历

具体实现:

1.使用max函数找到数组中的最大值和对应的索引

max_val = max(nums)

max_idx = nums.index(max_val)

2.最大值为二叉树根节点

root = TreeNode(nums[max_idx])

3.递归调用构造左右子树

root.left = self.constructMaximumBinaryTree(nums[:max_idx])
root.right = self.constructMaximumBinaryTree(nums[max_idx+1:])

代码:

 

class Solution {
    public TreeNode constructMaximumBinaryTree(int[] nums) {
        return constructMaximumBinaryTree1(nums, 0, nums.length);
    }

    public TreeNode constructMaximumBinaryTree1(int[] nums, int leftIndex, int rightIndex) {
        if (rightIndex - leftIndex < 1) {// 没有元素了
            return null;
        }
        if (rightIndex - leftIndex == 1) {// 只有一个元素
            return new TreeNode(nums[leftIndex]);
        }
        int maxIndex = leftIndex;// 最大值所在位置
        int maxVal = nums[maxIndex];// 最大值
        for (int i = leftIndex + 1; i < rightIndex; i++) {
            if (nums[i] > maxVal){
                maxVal = nums[i];
                maxIndex = i;
            }
        }
        TreeNode root = new TreeNode(maxVal);
        // 根据maxIndex划分左右子树
        root.left = constructMaximumBinaryTree1(nums, leftIndex, maxIndex);
        root.right = constructMaximumBinaryTree1(nums, maxIndex + 1, rightIndex);
        return root;
    }
}

 

class Solution {
    public TreeNode constructMaximumBinaryTree(int[] nums) {
        return helper(nums, 0, nums.length - 1);
    }
    public TreeNode helper(int[] nums, int left, int right){
        if (left > right) return null;
        if (right == left) return new TreeNode(nums[left]);
        int idx = left;
        int maxVal = nums[idx];
        for (int i = left + 1; i <= right; i++) {
            if (nums[i] > maxVal) {
                maxVal = nums[i];
                idx = i;
            }
        }
        TreeNode root = new TreeNode(maxVal);
        root.left = helper(nums, left, idx - 1);
        root.right = helper(nums, idx + 1, right);
        return root;
    }
}

 

 

 105、从前序和中序遍历结果构造二叉树

 

 

 

 

 

基本思想:

确定根节点的值,把根节点确定出来,然后递归构造左右子树

具体实现:

1.找到根节点

前序遍历第一个值为根节点

root=TreeNode(preorder[0])

根节点在中序遍历中的位置为切割点

mid=inorder.index(preorder[0])

2.切割

切割前序数组,切成前序左数组和前序右数组

切割中序数组,切成中序左数组和中序右数组

 

3.递归构建左右子树

 

步骤:

  • 第一步:如果数组大小为零的话,说明是空节点了。

  • 第二步:如果不为空,那么取前序数组第一个元素作为节点元素。

  • 第三步:找到前序数组第一个元素在中序数组的位置,作为切割点

  • 第四步:切割前序数组,切成前序左数组和前序右数组

  • 第五步:切割中序数组,切成中序左数组和中序右数组

  • 第六步:递归处理左区间和右区间

代码:

 

class Solution {
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        return helper(preorder, 0, preorder.length - 1, inorder, 0, inorder.length - 1);
    }

    public TreeNode helper(int[] preorder, int preLeft, int preRight,
                           int[] inorder, int inLeft, int inRight) {
        // 递归终止条件
        if (inLeft > inRight || preLeft > preRight) return null;

        // val 为前序遍历第一个的值,也即是根节点的值
        // idx 为根据根节点的值来找中序遍历的下标
        int idx = 0;
int val = preorder[preLeft]; TreeNode root = new TreeNode(val); for (int i = inLeft; i <= inRight; i++) { if (inorder[i] == val) { idx = i; break; } } // 根据 idx 来递归找左右子树 root.left = helper(preorder, preLeft + 1, preLeft + (idx - inLeft), inorder, inLeft, idx - 1); root.right = helper(preorder, preLeft + (idx - inLeft) + 1, preRight, inorder, idx + 1, inRight); return root; } }

 

 

 

106、从后序和中序遍历结果构造二叉树

 

 

 

class Solution {
    public TreeNode buildTree(int[] inorder, int[] postorder) {
        return buildTree1(inorder, 0, inorder.length, postorder, 0, postorder.length);
    }
    public TreeNode buildTree1(int[] inorder, int inLeft, int inRight,
                               int[] postorder, int postLeft, int postRight) {
        // 没有元素了
        if (inRight - inLeft < 1) {
            return null;
        }
        // 只有一个元素了
        if (inRight - inLeft == 1) {
            return new TreeNode(inorder[inLeft]);
        }
        // 后序数组postorder里最后一个即为根结点
        int rootVal = postorder[postRight - 1];
        TreeNode root = new TreeNode(rootVal);
        int rootIndex = 0;
        // 根据根结点的值找到该值在中序数组inorder里的位置
        for (int i = inLeft; i < inRight; i++) {
            if (inorder[i] == rootVal) {
                rootIndex = i;
                break;
            }
        }
        // 根据rootIndex划分左右子树
        root.left = buildTree1(inorder, inLeft, rootIndex,
                postorder, postLeft, postLeft + (rootIndex - inLeft));
        root.right = buildTree1(inorder, rootIndex + 1, inRight,
                postorder, postLeft + (rootIndex - inLeft), postRight - 1);
        return root;
    }
}

 

 

class Solution {
    public TreeNode buildTree(int[] inorder, int[] postorder) {
        return helper(inorder, 0, inorder.length - 1, postorder, 0, postorder.length - 1);
    }
    public TreeNode helper(int[] inorder, int inLeft, int inRight, int[] postorder, int postLeft, int postRight) {
        if (inLeft > inRight || postLeft > postRight) return null;
        int idx = 0;
        int val = postorder[postRight];
        TreeNode root = new TreeNode(val);
        for (int i = inLeft; i <= inRight; i++) {
            if (val == inorder[i]) {
                idx = i;
                break;
            }
        }
        root.left = helper(inorder, inLeft, idx - 1, postorder, postLeft, postLeft + (idx - inLeft) - 1);
        root.right = helper(inorder, idx + 1, inRight, postorder, postLeft + (idx - inLeft), postRight - 1);
        return root;
    }
}

 

 

 

posted @ 2020-11-27 22:54  最近饭吃的很多  阅读(105)  评论(0编辑  收藏  举报