力扣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; } }