文章目录
【654.最大二叉树】
思路:和已知后序和中序遍历构造二叉树类似,一个一个找根节点然后分隔数组,注意每次分隔不用定义新的数组,而是通过下标索引直接在原数组上操作
c++
TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
TreeNode* node = new TreeNode(0);
if (nums.size() == 1) {
node->val = nums[0];
return node;
}
// 找到数组中最大的值和对应的下标
int maxValue = 0;
int maxValueIndex = 0;
for (int i = 0; i < nums.size(); i++) {
if (nums[i] > maxValue) {
maxValue = nums[i];
maxValueIndex = i;
}
}
node->val = maxValue;
// 最大值所在的下标左区间 构造左子树
if (maxValueIndex > 0) {
vector<int> newVec(nums.begin(), nums.begin() + maxValueIndex);
node->left = constructMaximumBinaryTree(newVec);
}
// 最大值所在的下标右区间 构造右子树
if (maxValueIndex < (nums.size() - 1)) {
vector<int> newVec(nums.begin() + maxValueIndex + 1, nums.end());
node->right = constructMaximumBinaryTree(newVec);
}
return node;
}
【617.合并二叉树】
递归法:前序遍历,每次传入两个结点进行操作,容易理解。
c++
TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) {
if(root1 == nullptr) return root2;
if(root2 == nullptr) return root1;
TreeNode* node = new TreeNode(0);
node->val = root1->val + root2->val;
node->left = mergeTrees(root1->left, root2->left);
node->right = mergeTrees(root1->right, root2->right);
return node;
}
迭代法:把两个树的节点同时加入队列进行比较,模拟层序遍历
c++
TreeNode* mergeTrees(TreeNode* t1, TreeNode* t2) {
if (t1 == NULL) return t2;
if (t2 == NULL) return t1;
queue<TreeNode*> que;
que.push(t1);
que.push(t2);
while(!que.empty()) {
TreeNode* node1 = que.front(); que.pop();
TreeNode* node2 = que.front(); que.pop();
// 此时两个节点一定不为空,val相加
node1->val += node2->val;
// 如果两棵树左节点都不为空,加入队列
if (node1->left != NULL && node2->left != NULL) {
que.push(node1->left);
que.push(node2->left);
}
// 如果两棵树右节点都不为空,加入队列
if (node1->right != NULL && node2->right != NULL) {
que.push(node1->right);
que.push(node2->right);
}
// 当t1的左节点为空 t2左节点不为空,就赋值过去
if (node1->left == NULL && node2->left != NULL) {
node1->left = node2->left;
}
// 当t1的右节点为空 t2右节点不为空,就赋值过去
if (node1->right == NULL && node2->right != NULL) {
node1->right = node2->right;
}
}
return t1;
}
【700.二叉搜索树中的搜索】
二叉搜索树 是一个有序树:
- 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
- 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
- 它的左、右子树也分别为二叉搜索树
思路:都挺好想的,一下就懂。
递归法:
c++
TreeNode* searchBST(TreeNode* root, int val) {
if(root == nullptr || root->val == val) return root;
if(root->val > val){
return searchBST(root->left, val);
}
if(root->val < val){
return searchBST(root->right, val);
}
return nullptr;
}
迭代法:
c++
TreeNode* searchBST(TreeNode* root, int val) {
while(root != nullptr){
if(root->val > val){
root = root->left;
}else if(root->val < val){
root = root->right;
}else return root;
}
return root;
}
【98.验证二叉搜索树】
思路:中序遍历下,输出的二叉搜索树节点的数值是有序序列。
有了这个特性,验证二叉搜索树,就相当于变成了判断一个序列是不是递增的了。
递归法:
c++
vector<int> vec;
void travelsal(TreeNode* root){
if(root == nullptr) return;
travelsal(root->left);
vec.push_back(root->val);// 将二叉搜索树转换为有序数组
travelsal(root->right);
}
bool isValidBST(TreeNode* root) {
travelsal(root);
for(int i = 1; i < vec.size(); i++){
if(vec[i] <= vec[i-1]) return false;
}
return true;
}
迭代法:模拟中序遍历,需要一个pre来记录前一个结点,还是有点绕,需要多思考熟悉。
c++
bool isValidBST(TreeNode* root) {
stack<TreeNode*> st;
TreeNode* cur = root;
TreeNode* pre = nullptr;// 记录前一个结点
while(!st.empty() || cur != nullptr){
if(cur != nullptr){
st.push(cur);
cur = cur->left;// 左
}else{
cur = st.top();// 中
st.pop();
if(pre != nullptr && cur->val <= pre->val) return false;
pre = cur;// 保存前一个访问的节点
cur = cur->right;// 右
}
}
return true;
}
ps:我们要比较的是 左子树所有节点小于中间节点,右子树所有节点大于中间节点。
不能只判断左节点小于其根节点,右结点大于其根节点
反例:
