654.最大二叉树
构造最大二叉树,与105、106 题目类似
注意: 凡是构造二叉树的题目一律用前序遍历
前序遍历是 中左右, 因为只有构造了中结点, 才能去构造它的左右孩子结点
class Solution {
public:
TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
return traversal(nums, 0, nums.size());
}
TreeNode* traversal(vector<int>& nums, int numsBegin, int numsEnd) {
if (numsBegin >= numsEnd) return NULL;
TreeNode* node;
int maxId = numsBegin;
for (int i = numsBegin + 1; i < numsEnd; i++) {
if (nums[i] > nums[maxId]) maxId = i;
}
node = new TreeNode(nums[maxId]);
// 左闭右开[ )
int numsLeftBegin = numsBegin;
int numsLeftEnd = maxId;
int numsRightBegin = maxId + 1;
int numsRightEnd = numsEnd;
node->left = traversal(nums, numsLeftBegin, numsLeftEnd);
node->right = traversal(nums, numsRightBegin, numsEnd);
return node;
}
};
617.合并二叉树
使用递归前中后序遍历都是可以的,只不过前序遍历是最容易理解的。
为了减小空间的损耗,不去定义新的树,直接在树1的基础之上该变其结构。
class Solution {
public:
TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) {
return traversal(root1, root2);
}
TreeNode* traversal(TreeNode* tree1, TreeNode* tree2) {
if (tree1 == NULL) return tree2;
if (tree2 == NULL) return tree1;
tree1->val += tree2->val;
tree1->left = traversal(tree1->left, tree2->left);
tree1->right = traversal(tree1->right, tree2->right);
return tree1;
}
};
700.二叉搜索树中的搜索
二叉搜索树是一个有序树:
- 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
- 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
- 它的左、右子树也分别为二叉搜索树
二叉搜索树自身特性,帮助我们明确了搜索的方向
遇到搜索树,一定要想着中序遍历 : 左 中 右,这样才能利用上特性。
class Solution {
public:
// 迭代法
TreeNode* searchBST(TreeNode* root, int val) {
while (root != NULL) {
if (val < root->val) root = root-> left;
else if (val > root->val) root = root->right;
else return root;
}
return NULL;
}
};
class Solution {
public:
// 递归法
TreeNode* searchBST(TreeNode* root, int val) {
if (root == NULL || root->val == val) return root;
TreeNode* result = NULL;
if (val < root->val) {
result = searchBST(root->left, val);
}
if (val > root->val) {
result = searchBST(root->right, val);
}
return result;
}
};
98.验证二叉搜索树
按照 二叉搜索树的特性去遍历,看其是否是一个 有序数组。即:对于二叉搜索树来说,使用 中序遍历得到 的数组为一个递增 的数组。
对于判断一个数组是否有序,可以不需要额外去定义一个变量来比较,可以通过前后两者进行比较,对于二叉树而言,即为前一个结点和后一个结点进行比较。
对于该题而言,结点的值中会出现int 类型的最小值,所以在比较时,我们只能比int 最小值还要小,所以定义的为 long long max val = long_min
暴力法
class Solution {
public:
// 暴力法:按照 二叉搜索树的特性去遍历,看其是否是一个 有序数组。
vector<int> nums;
bool isValidBST(TreeNode* root) {
nums.clear();
long long max = LONG_MIN;
traversal(root);
for (int i : nums) {
std::cout << i << endl;
if (i > max) {
max = i;
}
else {
return false;
}
}
return true;
}
void traversal(TreeNode* node) {
if (node == NULL) return;
traversal(node->left);
nums.push_back(node->val);
traversal(node->right);
return;
}
};
递归法
class Solution {
public:
// 递归法1
long long max = LONG_MIN;
bool isValidBST(TreeNode* root) {
if (root == NULL) return true;
bool left = isValidBST(root->left);
if (root->val > max) {
max = root->val;
} else return false;
bool right = isValidBST(root->right);
return left && right;
}
};
递归法 双指针优化
class Solution {
public:
// 递归法2:利用双指针法 对其进行优化
TreeNode* pre = NULL; // 指向当前结点的前一个结点(往下)
bool isValidBST(TreeNode* root) {
if (root == NULL) return true;
bool left = isValidBST(root->left);
if (pre != NULL && pre->val >= root->val) return false;
pre = root;
bool right = isValidBST(root->right);
return left && right;
}
};