今日内容
- 654.最大二叉树
- 617.合并二叉树
- 700.二叉搜索树中的搜索
- 98.验证二叉搜索树
一、构造最大二叉树
由于本题是找到最大节点的值作为根节点,然后左侧数组构造左子树,右侧数组构造右子树。
其中肯定是有一个递归的过程,所以就涉及到递归三部曲:
1、确定顶柜函数的参数和返回值
构造二叉树,所以返回的是头节点,然后参数使我们依据的存放元素的数组
Treenode* constructTree(vector<int>& nums)
2、终止条件
题中说输入的数组大小一定大于等于1,故不考虑数组为空的情况,那如果遍历中数组大小等于1,说明此时已经是最后一个节点也就是叶子节点。
TreeNode* node = new TreeNode(0);
if (nums.size() == 1) {
node->val = nums[0];
return node;
}
3、单层递归逻辑
先找到最大值,用最大值构造根节点,下标用于分割数组
然后再下标的左区间构造左子树,右区间构造右子树
int maxValue = 0;
int maxValueIndex = 0;
for (int i = 0; i < nums.size(); i++) {
if (nums[i] > maxValue) {
maxValue = nums[i];
maxValueIndex = i;
}
}
TreeNode* node = new TreeNode(0);
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);
}
下面是整体代码
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
TreeNode* node =new TreeNode(0);
if(nums.size()==1){
node->val=nums[0];
return node;
}
int maxvalue=0;
int maxvindex=0;
for(int i=0;i<nums.size();i++){
if(nums[i]>maxvalue){
maxvalue=nums[i];
maxvindex=i;
}
}
node->val=maxvalue;
if(maxvindex>0){
vector<int> newVec(nums.begin(),nums.begin()+ maxvindex);
node->left =constructMaximumBinaryTree(newVec);
}
if(maxvindex<(nums.size()-1)){
vector<int> newVec(nums.begin()+maxvindex+1,nums.end());
node->right =constructMaximumBinaryTree(newVec);
}
return node;
}
};
今天有脑子有耐心分析代码,明显比上次好多了,逻辑清晰一点。
二、合并二叉树
这题头脑一热自己写了一半,然后发现写的太麻烦了。
先上代码:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) {
if(root1==NULL) return root2;
if(root2==NULL) return root1;
root1->val+=root2->val;
root1->left =mergeTrees(root1->left,root2->left);
root1->right =mergeTrees(root1->right,root2->right);
return root1;
}
};
递归三部曲:
1、确定参数和返回值
返回的应该是个树的根节点,然后参数是两个未合并的树。
TreeNode* mergeTrees(TreeNode* t1, TreeNode* t2)
2、确定终止条件
如果两个树遍历节点任意为空,就返回另一个节点
其中也包含两个均为空的情况,但这种情况是返回NULL,所以也是一样的。
if (t1 == NULL) return t2; // 如果t1为空,合并之后就应该是t2
if (t2 == NULL) return t1; // 如果t2为空,合并之后就应该是t1
3、单层递归逻辑
这时候逻辑就是都不为空的情况,所以先把t1和t2的值和到t1中,然后将左子树和右子树进行递归,参数就是t1和t2的子树。
t1->val += t2->val; // 中
t1->left = mergeTrees(t1->left, t2->left); // 左
t1->right = mergeTrees(t1->right, t2->right); // 右
return t1;
三、二叉搜索树的搜索
这道题利用二叉搜索树的特性还是蛮简单的,所以就先写了一遍。
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
TreeNode* searchBST(TreeNode* root, int val) {
if(root==NULL){
return NULL;
}
if(root->val==val){
return root;
}
else if(root->val>val){
return searchBST(root->left,val);
}
else{
return searchBST(root->right,val);
}
}
};
看了一遍题解发现是把前两种情况合并了,但思路是一样的,依然还是递归三部曲走一下:
1、确定函数的参数和返回值
题目要求返回子树所以返回搜索数值所在的节点。参数就是根节点和所要搜索的数值。
TreeNode* searchBST(TreeNode* root, int val)
2、确定终止条件
只要是遇到空节点和所需要的节点,就返回该节点(其实和我上面的逻辑是一样的,只是更优化,逻辑上root为空时返回的也是不存在的空,所以是一种情况)
if (root == NULL || root->val == val) return root;
3、单层递归逻辑
这里题解是先设了一个结果变量,将两种i情况的解放在了result中,这样更直观吧,我是直接在两种情况中就直接返回了(其实和题解整体代码的第二版一样)。
TreeNode* result = NULL;
if (root->val > val) result = searchBST(root->left, val);
if (root->val < val) result = searchBST(root->right, val);
return result;
迭代法
class Solution {
public:
TreeNode* searchBST(TreeNode* root, int val) {
TreeNode* node =root;
while(1){
if(node==NULL||node->val==val){
return node;
}
else if(node->val>val){
node=node->left;
}
else{
node=node->right;
}
}
}
};
还是自己尝试写了一遍,然后看题解发现太麻烦了,emmmm其实逻辑是一样的,只是我的循环条件是恒成立的,而题解的循环条件我是依据迭代的题解在循环中处理了。
class Solution {
public:
TreeNode* searchBST(TreeNode* root, int val) {
while (root != NULL) {
if (root->val > val) root = root->left;
else if (root->val < val) root = root->right;
else return root;
}
return NULL;
}
};
四、验证二叉搜索树
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<int> vec;
void traversal(TreeNode* node){
if(node==NULL) return;
traversal(node->left);
vec.push_back(node->val);
traversal(node->right);
}
bool isValidBST(TreeNode* root) {
traversal(root);
for(int i=1;i<vec.size();i++){
if(vec[i]<=vec[i-1]) return false;
}
return true;
}
};
刚自己写半天发现陷进陷阱。
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
long long maxval =LONG_MIN;
bool isValidBST(TreeNode* root) {
if(root==NULL) return true;
bool left =isValidBST(root->left);
if(maxval<root->val) maxval = root->val;
else return false;
bool right =isValidBST(root->right);
return left&&right;
}
};
这是递归的代码,主要思路是利用中序遍历,使maxval从最左侧节点比较,是否小于右侧的值。
迭代则是中序稍加改动
class Solution {
public:
bool isValidBST(TreeNode* root) {
stack<TreeNode*> st;
TreeNode* cur = root;
TreeNode* pre = NULL; // 记录前一个节点
while (cur != NULL || !st.empty()) {
if (cur != NULL) {
st.push(cur);
cur = cur->left; // 左
} else {
cur = st.top(); // 中
st.pop();
if (pre != NULL && cur->val <= pre->val)
return false;
pre = cur; //保存前一个访问的结点
cur = cur->right; // 右
}
}
return true;
}
};