学习资料:代码随想录
文中含LLM生成内容,不一定对
力扣题目地址
思路:不断寻找该部分的最大值去切割数组,不断递归,到在左闭右开区间不成立时,返回空节点。
/**
* 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* traversal(vector& nums,int leftIndex,int rightIndex){
if(rightIndex<=leftIndex) return nullptr; //左闭右开区间
int maxValueIndex=leftIndex;
for(int i=leftIndex+1;inums[maxValueIndex]){
maxValueIndex=i;
}
}
TreeNode* root = new TreeNode(nums[maxValueIndex]);
root->left = traversal(nums,leftIndex,maxValueIndex); //操作原数组,区间不要写错了。
root->right = traversal(nums,maxValueIndex+1,rightIndex);
return root;
}
TreeNode* constructMaximumBinaryTree(vector& nums) {
return traversal(nums,0,nums.size()); //起手就是左闭右开
}
};
力扣题目链接
思路:把树都并到第一颗,递归法,tree1遍历到空,就返回到tree2;tree2遍历到空,就返回到tree1;
/**
* 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* t1, TreeNode* t2) {
if (t1 == NULL) return t2;
if (t2 == NULL) return t1;
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* mergeTrees(TreeNode* root1, TreeNode* root2) {
if(root1==nullptr) return root2;
if(root2==nullptr) return root1;
queue que;
que.push(root1);
que.push(root2);
while(!que.empty()){ //不需要层相关的数据了,就不加for了
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);
}
if(!node1->left&&node2->left){
node1->left=node2->left; //不用push了,直接往里放.如果 t1->left 不为空,而 t2->left 为空,则根本不需要处理。原因是 t1 已经有左子节点(t1->left != NULL),并且 t2 没有需要合并的左子节点(t2->left == NULL),无需任何操作,t1->left 保持不变即可。
}
if(!node1->right&&node2->right){
node1->right=node2->right;
}
}
return root1;
}
};
力扣题目地址
思路:搜索树是有序的,按排序搜索,递归:
/**
* 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==nullptr||root->val==val) return root;
TreeNode* result = nullptr;
if(root->val>val) { //充分利用搜索树性质
result=searchBST(root->left,val);
}
if(root->valright,val);
}
return result;
}
};
迭代:
/**
* 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) {
while(root!=nullptr){
if(root->val>val) root=root->left;
else if(root->valright;
else{return root;}
}
return nullptr;
}
};
力扣题目链接
思路1:遍历转换成数组,然后验证是否有序
class Solution {
private:
vector 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;
}
};
思路2:递归,实时更新最大值,因为搜索树不是简单的一个节点处左中右越来越大就行,这里有双指针的样子了
/**
* 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 maxValue=LONG_MIN; //要用中序遍历,数会越来越大,所以定义一个最大值;因为测试集中有int最小值,所以用LONG_MIN
bool isValidBST(TreeNode* node) {
if(node==nullptr) return true;
bool left=isValidBST(node->left);
if(node->val>maxValue) maxValue=node->val;
else {return false;}
bool right=isValidBST(node->right);
return left&&right;
}
};
思路:双指针法:将前一个值记录下来与本值比较
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; //如果根节点返回false的话,往上也没有要返回的了,不论left和right也就返回false了
pre = root; // 记录前一个节点
bool right = isValidBST(root->right);
return left && right;
}
};
但是语法上true和false不是同一级别的吗,为什么你这里看起来false比true优先级要高,遇到false就都不管了?
你提到的问题其实是关于 短路求值(short-circuit evaluation) 和 递归的早期返回 的。
在 C++ 中,&&
(逻辑与)运算符是使用短路求值的。当我们写 A && B
时:
A
为 false
,则 B
不会被求值,因为无论 B
是什么,整个表达式都会是 false
。A
为 true
,那么会继续计算 B
。这种行为应用于你代码中的 return left && right;
。具体来说:
left
为 false
,那么 right
不会被求值,直接返回 false
。left
为 true
,那么才会判断 right
,然后返回最终结果。在你的代码中,递归的返回值在 left
和 right
上起到了决定性的作用:
left
),然后判断当前节点值与 pre
的值。如果违反了条件,就会返回 false
,并且不会再继续检查右子树,因为我们已经知道这部分不合法。left
)是 false
,那么根据短路求值的规则,right
就不会被求值,直接返回 false
。left
)是 true
,那么才会递归右子树(right
),并返回 left && right
的结果。&&
)的短路求值:一旦 left
为 false
,整个表达式的值就会是 false
,不再计算 right
。return false
):如果在递归过程中发现不符合二叉搜索树规则,立即返回 false
并结束当前递归。因此,left
和 right
的返回值并不意味着 优先级。实际上,false
不会影响到 true
的判断,关键是 一旦某一部分不符合要求,后续部分就无需计算。