题目一:
解法一:(递归)
解题思路:这个题主要就是按照题目的要求进行即可,主要是要注意递归终止条件的判断。
构造树一般采用的是前序遍历,因为先构造中间节点,然后递归构造左子树和右子树。
- 确定递归函数的参数和返回值
参数就是传入的是存放元素的数组,返回该数组构造的二叉树的头结点,返回类型是指向节点的指针。
var constructMaximumBinaryTree = function(nums) {}
- 确定终止条件
题目中说了输入的数组大小一定是大于等于1的,所以我们不用考虑小于1的情况,那么当递归遍历的时候,如果传入的数组大小为1,说明遍历到了叶子节点了。
那么应该定义一个新的节点,并把这个数组的数值赋给新的节点,然后返回这个节点。 这表示一个数组大小是1的时候,构造了一个新的节点,并返回。
const node = new TreeNode(0)
if (nums.length === 1) {
node.val = nums[0]
return node
}
- 确定单层递归的逻辑(三步)
- 先要找到数组中最大的值和对应的下标, 最大的值构造根节点,下标用来下一步分割数组。
let maxValue = 0
let maxValueIndex = 0
for (let i = 0; i < nums.length; i++) {
if (nums[i] > maxValue) {
maxValue = nums[i]
maxValueIndex = i
}
}
node.val = maxValue
- 最大值所在的下标左区间 构造左子树
这里要判断maxValueIndex > 0,因为要保证左区间至少有一个数值。
if (maxValueIndex > 0) {
vector<int> newVec(nums.begin(), nums.begin() + maxValueIndex);
node->left = constructMaximumBinaryTree(newVec);
}
- 最大值所在的下标右区间 构造右子树
判断maxValueIndex < (nums.size() - 1),确保右区间至少有一个数值。
var constructMaximumBinaryTree = function(nums) {
const node = new TreeNode(0)
if (nums.length === 1) {
node.val = nums[0]
return node
}
let maxValue = 0
let maxValueIndex = 0
for (let i = 0; i < nums.length; i++) {
if (nums[i] > maxValue) {
maxValue = nums[i]
maxValueIndex = i
}
}
node.val = maxValue
if (maxValueIndex > 0) {
node.left = constructMaximumBinaryTree(nums.slice(0, maxValueIndex))
}
if (maxValueIndex < nums.length - 1) {
node.right = constructMaximumBinaryTree(nums.slice(maxValueIndex + 1))
}
return node
};
优化:
每次分隔不用定义新的数组,而是通过下标索引直接在原数组上操作。
一般情况来说:如果让空节点(空指针)进入递归,就不加if,如果不让空节点进入递归,就加if限制一下, 终止条件也会相应的调整。
var constructMaximumBinaryTree = function (nums) {
const BuildTree = (arr, left, right) => {
if (left > right)
return null;
let maxValue = -1;
let maxIndex = -1;
for (let i = left; i <= right; ++i) {
if (arr[i] > maxValue) {
maxValue = arr[i];
maxIndex = i;
}
}
let root = new TreeNode(maxValue);
root.left = BuildTree(arr, left, maxIndex - 1);
root.right = BuildTree(arr, maxIndex + 1, right);
return root;
}
let root = BuildTree(nums, 0, nums.length - 1);
return root;
};