在看过深度搜索和广度搜索之后,就想着从Leetcode上找一些题刷一下,
本来以为可以日刷五十道题,最后成了每天刷五道,这里进行周总结。
我的代码好多都是看别人的,先理论学习
1 124.二叉树的最大路径和
传送门:https://leetcode-cn.com/problems/binary-tree-maximum-path-sum/
//这个题的意思是返回一个最大路径的和,不是返回子树的和。
-10 / \ 9 20 / \ 15 7
用这个图来解释一下,这个图中最大路径和是42,很容易算到,但是当树变为如下形式的时候
10 / \ 9 20 / \ 15 7
最大和为54,是因为一条路径不可能同时经过一个节点的左子树和右子树。
//可能是因为我理解的不好,接下来进行代码:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
int maxPathSum(TreeNode* root, int &val)
{
if (root == nullptr) return 0;
int left = maxPathSum(root->left, val);
int right = maxPathSum(root->right, val);
int lmr = root->val + max(0, left) + max(0, right);
//lmr记录的就是左右加上根节点的值。
int ret = root->val + max(0, max(left, right));
val = max(val, max(lmr, ret));
//cout<<root->val<<" "<<left<<" "<<right<<" "<<lmr<<" "<<ret<<" "<<val<<endl;
return ret;
//为什么需要lmr和ret呢?
//ret就是看我们第二颗树,当走到根节点的时候,我们需要的是左和右节点的最大值,这里涉及到的只是右节点的一个子树,所以需要有ret去取到这个右节点路径上的最大值。
//lmr就是记录本节点加上左和右节点的最大值
//子函数返回的是一个分支的最大值。
// 最后主函数返回这二者最大值。
}
int maxPathSum(TreeNode* root)
{
int val = INT_MIN;
maxPathSum(root, val);
return val;
}
//勉强解释一下,就是这样的,res记录最大值,post返回值记录的是左右子树中的较大值加上本节点的值
//为什么要这样呢?
//我的理解出现了问题,我的理解是要返回节点最大值
//它这里的题意是有一条路径,得到·该路径的最大值。
};
2 110. 平衡二叉树
传送门:https://leetcode-cn.com/problems/balanced-binary-tree/
一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过1,就很容易理解。
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
int f=0;
int dfs(TreeNode* root){
if(root==NULL) return 0;
int l=dfs(root->left);
int r=dfs(root->right);
if(abs(l-r)>1) f=1;
return max(l,r)+1;
//当root时候,l和r记录的是其左右子树的最大高度,所以比较就完事了
}
bool isBalanced(TreeNode* root) {
dfs(root);
if(f) return false;
else return true;
}
};
3 199.二叉树的右视图
给定一棵二叉树,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。
传送门:https://leetcode-cn.com/problems/binary-tree-right-side-view/
输入: [1,2,3,null,5,null,4]
输出: [1, 3, 4]
解释:
1 <---
/ \
2 3 <---
\ \
5 4 <---
感觉题目说的也是比较清楚了,开始代码:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
vector<int> rightSideView(TreeNode* root) {
if(!root)
return {};
vector<int> ans;
queue<TreeNode*> que;
que.push(root);
while(!que.empty()) {
int len = que.size();
for(int i = 0; i< len; i++) {
auto q = que.front();
que.pop();
if(i == len-1) {//这个就是到本层的最后一个元素
ans.push_back(q->val);
}
if(q->left)
que.push(q->left);
if(q->right)
que.push(q->right);
}
}
return ans;
}
};
queue这个容器在我最近几天就见过很多次,但我还是不会活用。queue特点是先进先出。
这里给大家解释一下while里面的代码:
在while之前,队列就保存了根值,所以肯定可以进入while,用len保存长度,pop()就是出队列,两个if就是将左右子树入队列
整个for结束后,queue就保存了下一层的所有值。
i == len-1,说明已经到了最后一个元素,这时候就用vector容器保存改值。
4 98.验证二叉树
给定一个二叉树,判断其是否是一个有效的二叉搜索树。
假设一个二叉搜索树具有如下特征:
节点的左子树只包含小于当前节点的数。
节点的右子树只包含大于当前节点的数。
所有左子树和右子树自身必须也是二叉搜索树。
///这个就是说要保证左子树的所有节点值小于根节点的值,右节点的所有节点值大于根节点的值
在自己内部也要符合相应条件。
下面开始代码
class Solution {
public:
bool helper(TreeNode* root, long long low, long long high) {
if (root == nullptr) return true;
if (root -> val <= low || root -> val >= high) return false;
return helper(root -> left, low, root -> val) && helper(root -> right, root -> val, high);
}
bool isValidBST(TreeNode* root) {
return helper(root, LONG_MIN, LONG_MAX);
}
};
5 99.恢复二叉树
二叉搜索树中的两个节点被错误地交换。
请在不改变其结构的情况下,恢复这棵树。
//额如果二叉树的性质是这样的话,那我前面用到的二叉树是什么?
这个重点就是只有两个节点是颠倒位置的
//同时还要保证上一题的性质不变
所以通过和根值比较,从左子树中找最大值,从右子树中找最小值,如果这是正确的二叉树,说明是找不到这两个值的。
下面开始代码
class Solution {
public:
TreeNode* mx;
TreeNode* mn;
void findmax(TreeNode* node) {
if(node == nullptr) {
return;
}
if(node->val > mx->val) {
mx = node;
}
findmax(node->left);
findmax(node->right);
}
void findmin(TreeNode* node) {
if(node == nullptr) {
return;
}
if(node->val < mn->val) {
mn = node;
}
findmin(node->left);
findmin(node->right);
}
void recoverTree(TreeNode* root) {
if(root == nullptr)
return;
mx = root;
mn = root;
findmax(root->left);
findmin(root->right);
if(mx->val > mn->val) {
auto tmp = mn->val;
mn->val = mx->val;
mx->val = tmp;
return;
}
recoverTree(root->left);
recoverTree(root->right);
}
};
也许我的解析只能我自己理解?还行吧
6 100.相同的树
给定两个二叉树,编写一个函数来检验它们是否相同。
如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。
就是各个节点一一比较
下面开始代码
class Solution {
public:
bool isSameTree(TreeNode* p, TreeNode* q) {
if(p == NULL && q == NULL) return true;
if(p == NULL || q == NULL) return false;
if(p->val!=q->val) return false;
return isSameTree(p->left, q->left)&&isSameTree(p->right, q->right);
}
};
7 101. 对称二叉树
给定一个二叉树,检查它是否是镜像对称的。
1 / \ 2 2 / \ / \ 3 4 4 3
就是根左子树的左节点和根右子树的右节点比较。根左子树的右节点和根右子树的左节点比较。
class Solution {
public:
bool isSymmetric(TreeNode* root) {
return ismirror(root,root);
}
bool ismirror(TreeNode* p, TreeNode *q) {
if(!p&&!q) ///如果这两个节点均为空的话
return true;
if(!p||!q)
return false;
if(p->val == q->val)
return ismirror(p->left,q->right)&&ismirror(p->right,q->left);
return false;
}
};