Day19_二叉树
19. 最大二叉树
654. 最大二叉树
思路:
首先 O ( n ) O(n) O(n) 找到数组中最大的元素下标,以该值为根节点,然后递归构建左右子树
递归的返回值是当前构造的节点
写法一: 将原函数改为递归函数
class Solution {
public:
TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
TreeNode *root = new TreeNode(0);
int nums_size = nums.size();
if (nums_size == 1) { // 叶结点
root->val = nums[0];
return root;
}
// 寻找当前数组中的最大值
int MaxIndex = 0;
for (int i = 1; i < nums_size; i++) {
if (nums[MaxIndex] < nums[i]) MaxIndex = i;
}
root->val = nums[MaxIndex];
// 构建左子树
if (MaxIndex > 0) {
vector<int> left_vec(nums.begin(), nums.begin() + MaxIndex);
root->left = constructMaximumBinaryTree(left_vec);
}
// 构建右子树
if (MaxIndex < nums_size - 1) {
vector<int> right_vec(nums.begin() + MaxIndex + 1, nums.end());
root->right = constructMaximumBinaryTree(right_vec);
}
// 递归返回值为当前子节点
return root;
}
};
写法二: 重新构造递归函数
由于写法一要多次使用迭代器构造新的数组,造成时间浪费,这里改用原数组,每次给出左右区间的下标。
class Solution {
private:
TreeNode* Traversal(vector<int>& nums, int left, int right) {
// 寻找最大值下标
int MaxIndex = left;
for (int i = left + 1; i < right; i++) {
if (nums[MaxIndex] < nums[i]) MaxIndex = i;
}
TreeNode* root = new TreeNode(nums[MaxIndex]);
// 构造左子树
if (MaxIndex > left) {
root->left = Traversal(nums, left, MaxIndex);
}
// 构造右子树
if (MaxIndex < right - 1) {
root->right = Traversal(nums, MaxIndex + 1, right);
}
// 返回当前节点
return root;
}
public:
TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
return Traversal(nums, 0, nums.size());
}
};
21. 合并二叉树
617. 合并二叉树
思路:
同时遍历两棵树,分三种情况:
- 两棵树都空了,说明当前分支合并结束,返回
- 两棵树都不空,合并时重叠,将两节点的值相加后继续合并
- 一棵树空另一棵不空,合并时直接选择不空的树,结束当前分支的合并
写法一:
class Solution {
public:
TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) {
TreeNode* root = new TreeNode(0);
// 遍历结束
if (root1 == NULL && root2 == NULL) return NULL;
// 重叠节点
else if (root1 != NULL && root2 != NULL ) {
root->val = root1->val + root2->val;
root->left = mergeTrees(root1->left, root2->left);
root->right = mergeTrees(root1->right, root2->right);
}
// 不重叠的节点
else {
if (root1 == NULL) root = root2;
else root = root1;
return root;
}
return root;
}
};
写法二:
对比之下,卡哥的写法真是简洁明了。
合并两棵树既可以用前中后序遍历均可,下面使用先序遍历。
class Solution {
public:
TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) {
if (root1 == NULL) return root2;
if (root2 == NULL) return root1;
TreeNode* root = new TreeNode(0);
root->val = root1->val + root2->val; // 前序
root->left = mergeTrees(root1->left, root2->left);
// 中序
root->right = mergeTrees(root1->right, root2->right);
// 后续
return root;
}
};
写法三:
迭代法:将 root2 合并到 root1
class Solution {
public:
TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) {
if (root1 == NULL) return root2;
if (root2 == NULL) return root1;
queue<TreeNode*> que;
que.push(root1);
que.push(root2);
while (!que.empty()) {
TreeNode* node1 = que.front(); que.pop();
TreeNode* node2 = que.front(); que.pop();
// 两个节点一定都不为空
node1->val += node2->val;
// 左子节点重叠
if (node1->left && node2->left) {
que.push(node1->left);
que.push(node2->left);
}
// 右子节点重叠
if (node1->right && node2->right) {
que.push(node1->right);
que.push(node2->right);
}
// node1->left 为空, node2->left 不为空
if (node1->left == NULL && node2->left)
node1->left = node2->left;
// node->right 为空,node2->right 不为空
if (node1->right == NULL && node2->right)
node1->right = node2->right;
// 均为空
}
return root1;
}
};
22. 二叉搜索树中的搜索
700. 二叉搜索树中的搜索
思路:
二叉搜索树,比根节点大去右子树查,比根节点小去左子树查,找到结果返回当前节点(子树),找到叶结点也没找到 val 则不在 BST 中
class Solution {
public:
TreeNode* searchBST(TreeNode* root, int val) {
if (root == NULL) return NULL;
TreeNode* ans = root;
if (root->val > val) ans = searchBST(root->left, val);
else if (root->val < val) ans = searchBST(root->right, val);
return ans;
}
};
迭代法:
这个迭代法太感人了,很难再有这么简单的迭代法了
class Solution {
public:
TreeNode* searchBST(TreeNode* root, int val) {
while (root) {
if (root->val > val) root = root->left;
else if (root->val < val) root = root->right;
else break;
}
return root;
}
};