参考链接:代码随想录
思路:做过根据中序后序数组构建二叉树后,这题比较容易,只需要找到最大值分割,然后递归构造即可。时间复杂度O(n),即为数组长度。
class Solution {
public:
int findMaxIndex(vector<int>& nums){//默认不为空
int max=INT_MIN;
int i,maxIndex;
for(i=0;i<nums.size();i++){
if(nums[i]>max){
max=nums[i];
maxIndex=i;
}
}
return maxIndex;
}
TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
if(nums.empty()){
return nullptr;
}
int maxIndex=findMaxIndex(nums);//也是分割点
TreeNode* root=new TreeNode(nums[maxIndex]);//建立根节点
vector<int> leftNums(nums.begin(),nums.begin()+maxIndex);//左闭右开
vector<int> rightNums(nums.begin()+maxIndex+1,nums.end());
root->left=constructMaximumBinaryTree(leftNums);
root->right=constructMaximumBinaryTree(rightNums);
return root;
}
};
不建立新vector的优化写法:
class Solution {
public:
int findMaxIndex(vector<int>& nums,int begin,int end){//默认不为空
int max=INT_MIN;
int i,maxIndex;
for(i=begin;i<end;i++){
if(nums[i]>max){
max=nums[i];
maxIndex=i;
}
}
return maxIndex;
}
TreeNode* traversal(vector<int>& nums,int begin,int end){//左闭右开
if(begin>=end){//数组为空
return nullptr;
}
int maxIndex=findMaxIndex(nums,begin,end);
TreeNode* root=new TreeNode(nums[maxIndex]);
int leftBegin=begin;
int leftEnd=maxIndex;
int rightBegin=maxIndex+1;
int rightEnd=end;
root->left=traversal(nums,leftBegin,leftEnd);
root->right=traversal(nums,rightBegin,rightEnd);
return root;
}
TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
return traversal(nums,0,nums.size());
}
};
思路:本题首先想到是正常遍历,采用前序遍历,同时遍历两棵树。
一开始错误代码:
class Solution {
public:
TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) {
TreeNode* node;
if(!root1&&!root2){//两个同时遍历
return nullptr;
}
else if(root1&&root2){
node=new TreeNode(root1->val+root2->val);
}
else if(root1){//只有左边
node=new TreeNode(root1->val);
}
else{
node=new TreeNode(root2->val);
}
node->left=mergeTrees(root1->left,root2->left);
node->right=mergeTrees(root1->right,root2->right);
return node;
}
};
主要问题是访问了空节点的左右孩子,造成runtime error。应该在一开始就优先判断返回情况,即两边有空的情况。
class Solution {
public:
TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) {
if(!root1&&!root2){//两个同时遍历
return nullptr;
}
if(root1&&!root2){
return root1;
}
if(!root1&&root2){//只有左边
return root2;
}
TreeNode* node=new TreeNode(root1->val+root2->val);
node->left=mergeTrees(root1->left,root2->left);
node->right=mergeTrees(root1->right,root2->right);
return node;
}
};
看解析发现不需要建立新节点,直接在T1上合并即可。
标答:
class Solution {
public:
TreeNode* mergeTrees(TreeNode* t1, TreeNode* t2) {
if (t1 == NULL) return t2; // 如果t1为空,合并之后就应该是t2
if (t2 == NULL) return t1; // 如果t2为空,合并之后就应该是t1
// 修改了t1的数值和结构
t1->left = mergeTrees(t1->left, t2->left); // 左
t1->right = mergeTrees(t1->right, t2->right); // 右
t1->val += t2->val; // 中
return t1;
}
};
迭代法pass。
思路:首先了解BST,即所有左子树节点小于根节点的值,所有右子树的节点大于根节点的值,且其所有子树都是二叉搜索树。采用递归法比较容易想到。
class Solution {
public:
TreeNode* searchBST(TreeNode* root, int val) {
if(!root){//一开始结束条件
return nullptr;
}
if(val==root->val){
return root;
}
else if(val<root->val){
return searchBST(root->left,val);
}
else{
return searchBST(root->right,val);
}
}
};
根为空和值找到了可以合并。
标答:
class Solution {
public:
TreeNode* searchBST(TreeNode* root, int val) {
if (root == NULL || root->val == val) return root;
TreeNode* result = NULL;
if (root->val > val) result = searchBST(root->left, val);
if (root->val < val) result = searchBST(root->right, val);
return result;
}
};
迭代法:由于BST的搜索路径已经固定好,不需要再使用栈和队列。
class Solution {
public:
TreeNode* searchBST(TreeNode* root, int val) {
TreeNode* cur=root;
while(cur&&cur->val!=val){
if(val<cur->val){
cur=cur->left;
}
else{
cur=cur->right;
}
}
return cur;
}
};
思路:二叉搜索树进行中序遍历,得到的序列递增,这就是我们的判断方法。判断序列递增的时候从头开始遍历,如果有一个不递增则break。只有序列长度为0或1或i遍历到倒数第二个,才说明序列递增。
class Solution {
public:
void traverse(TreeNode* root,vector<int> &inorder){
if(!root){
return;
}
traverse(root->left,inorder);
inorder.push_back(root->val);
traverse(root->right,inorder);
}
bool isValidBST(TreeNode* root) {
vector<int> inorder;
traverse(root,inorder);
int i;
for(i=0;i<inorder.size()-1;i++){
if(inorder[i]>=inorder[i+1]){
break;
}
}
if(inorder.empty()||inorder.size()== 1||i==inorder.size()-1){
return true;
}
return false;
}
};
标答简介一些:
class Solution {
private:
vector<int> vec;
void traversal(TreeNode* root) {
if (root == NULL) return;
traversal(root->left);
vec.push_back(root->val); // 将二叉搜索树转换为有序数组
traversal(root->right);
}
public:
bool isValidBST(TreeNode* root) {
vec.clear(); // 不加这句在leetcode上也可以过,但最好加上
traversal(root);
for (int i = 1; i < vec.size(); i++) {
// 注意要小于等于,搜索树里不能有相同元素
if (vec[i] <= vec[i - 1]) return false;
}
return true;
}
};
看标答发现可以在递归中直接比较,不用生成序列。
标答:
class Solution {
public:
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;
}
};
迭代法pass