2021-11-01每日刷题打卡
力扣——二叉树
965. 单值二叉树
如果二叉树每个节点都具有相同的值,那么该二叉树就是单值二叉树。
只有给定的树是单值二叉树时,才返回 true;否则返回 false。
示例 1:
输入:[1,1,1,1,1,null,1]
输出:true
这题考的就是树的遍历,比起链表的一个指针next,树有两个指针一个left,一个right。对于树的遍历我们最好用的就是递归的方式。全局变量设定一个bool类型flag初始化为true,每次遍历对比当前节点的val和其left与right的val值,如果不相等就设为false并直接结束所有程序返回flag,如果相等,就把root->left和root->right放入遍历中。最后返回flag。
/**
* 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:
bool flag=true;
bool isUnivalTree(TreeNode* root) {
if(root==NULL)return flag;
if(root->left!=NULL)
{
if(root->val!=root->left->val)flag=false;
isUnivalTree(root->left);
}
if(root->right!=NULL)
{
if(root->val!=root->right->val)flag=false;
isUnivalTree(root->right);
}
return flag;
}
};
另一种方法,不用全局变量。
/*
* 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:
bool isUnivalTree(TreeNode* root) {
bool flag=true;
int val=root->val;
dfs(root,flag,val);
return flag;
}
void dfs(TreeNode* root,bool &flag,int val)
{
if(root==NULL)return;
if(root->left!=NULL&&root->left->val!=val)flag=false;
if(root->right!=NULL&&root->right->val!=val)flag=false;
dfs(root->left,flag,val);
dfs(root->right,flag,val);
}
};
100. 相同的树
给你两棵二叉树的根节点 p 和 q ,编写一个函数来检验这两棵树是否相同。
如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。
示例 1:
输入:p = [1,2,3], q = [1,2,3]
输出:true
还是遍历树,不过这次是同时遍历两个,还要对比他们的val值。注意有一点,对比root->val时要考虑到节点为NULL的情况,这会使程序报错,所以对比值前我们应该先判断一下两个节点是否为NULL,如果两个都为NULL那就直接return结束程序,如果只有一个为空就把flag改为false(一个节点有值一个节点没值肯定不一样),如果都不为空就对比val。
/**
* 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:
bool isSameTree(TreeNode* p, TreeNode* q) {
bool flag=true;
dfs(p,q,flag);
return flag;
}
void dfs(TreeNode* p, TreeNode* q,bool &flag) {
if(!flag)return;
if(p==NULL&&q==NULL)return;
else if(p==NULL&&q!=NULL||p!=NULL&&q==NULL)
{
flag=false;
return;
}
if(p->val!=q->val)flag=false;
dfs(p->left,q->left,flag);
dfs(p->right,q->right,flag);
}
};
101. 对称二叉树和剑指 Offer 28. 对称的二叉树(这两题完全一样,我们放在一起说)
给定一个二叉树,检查它是否是镜像对称的。
例如,二叉树 [1,2,2,3,4,4,3] 是对称的。
1
/
2 2
/ \ /
3 4 4 3
这题就是上题的翻版,不过上题比较的是相同的子节点,即left和left比,right和right比。这题是left和right比,right和left比。
/**
* 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:
bool isSymmetric(TreeNode* root) {
bool flag=true;
dfs(root->left,root->right,flag);
return flag;
}
void dfs(TreeNode *p,TreeNode*q,bool &flag)
{
if(!flag)return;
if(!p&&!q)return;
else if(!p&&q || p&&!q)
{
flag=false;
return;
}
if(p->val!=q->val)flag=false;
dfs(p->left,q->right,flag);
dfs(p->right,q->left,flag);
}
};
AcWing——算法基础
842. 排列数字 - AcWing题库
给定一个整数 n,将数字 1∼n 排成一排,将会有很多种排列方法。
现在,请你按照字典序将所有的排列方法输出。
输入格式
共一行,包含一个整数 n。
输出格式
按字典序输出所有排列方案,每个方案占一行。
数据范围
1≤n≤7
输入样例:
3
输出样例:
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
这是我们第一次接触到DFS(深度优先搜索):一种用于遍历或搜索树或图的算法。 沿着树的深度遍历树的节点,尽可能深的搜索树的分支。当节点v的所在边都己被探寻过或者在搜寻时结点不满足条件,搜索将 回溯 到发现节点v的那条边的起始节点。整个进程反复进行直到所有节点都被访问为止。
这里排列数字的过程就是,我们要组成一个三位数的数字,第一位的可能性有1、2、3,我们先选1,第二位的可能性就剩2、3,我们选2,第三位就只剩3了,这条路搜索完毕,我们回溯到第二位上,选3为第二位,这样第三位就只剩2了,这条路也搜索完毕,我们回溯到第二位上,第二位可能的结果也都搜索完,我们回溯到第一位上,选数字2为第一位,然后继续搜…………这样最后我们就可以拿到所有的数。
我们准备一个int数组math来存放结果,一个bool数组st来告诉我们哪些数不能用,写一个递归函数dfs来进行我们的搜索,只有一个参数u,dfs进来先判断u和n是否相同,如果相同则输出math里存放的结果(要注意换行)。如果不相同我们就开始for(int i=0;i<n;i++)遍历,,判断st[i]的值是否为true,如果为true说明i表示的数我们已经使用过了,如果为false说明这个数我们没用过,可以放在第u位上,所有我们math[u]=i,同时把st[i]改为true告诉程序这个数已经被用过了。然后我们递归调用dfs(u+1),下面是回溯的操作,我们要把数变回原来的样子,即这个数没被使用过的样子st[i]=false。这样我们最后就能获得所有的结果。
#include<iostream>
using namespace std;
const int N=100010;
int n;
int math[N];
bool st[N];
void dfs(int u)
{
if(u==n)
{
for(int i=0;i<n;i++)printf("%d ",math[i]);
cout<<endl;
return;
}
for(int i=1;i<=n;i++)
{
if(!st[i])
{
st[i]=true;
math[u]=i;
dfs(u+1);
st[i]=false;
}
}
}
int main()
{
cin>>n;
for(int i=0;i<n;i++)scanf("%d",&math[i]);
dfs(0);
return 0;
}
843. n-皇后问题 - AcWing题库
n−n−皇后问题是指将 n 个皇后放在 n×n的国际象棋棋盘上,使得皇后不能相互攻击到,即任意两个皇后都不能处于同一行、同一列或同一斜线上。
现在给定整数 n,请你输出所有的满足条件的棋子摆法。
输入格式
共一行,包含整数 n。
输出格式
每个解决方案占 n 行,每行输出一个长度为 nn 的字符串,用来表示完整的棋盘状态。
其中 .
表示某一个位置的方格状态为空,Q
表示某一个位置的方格上摆着皇后。
每个方案输出完成后,输出一个空行。
注意:行末不能有多余空格。
输出方案的顺序任意,只要不重复且没有遗漏即可。
数据范围
1≤n≤9
输入样例:
4
输出样例:
.Q..
...Q
Q...
..Q.
..Q.
Q...
...Q
.Q..
DFS中最最最最最最最最最经典的八皇后问题,我们用的就是深度优先搜索的方法来写这道题,拿一个二维数组来模拟棋盘的样子,Q代表皇后的位置,我们的想法是先把皇后放在所有可能的地方上,每放一个皇后,就判断这个皇后同行同列同斜列上有没有皇后,如果有就说明这个方法不可行,然后回溯,然后再选新地方放…………以此类推。
#include<iostream>
using namespace std;
const int N=100;
int n;
char queen[N][N];
bool col[N],dg[N],udg[N];
void dfs(int u)
{
if(u==n)
{
for(int i=0;i<n;i++)cout<<queen[i]<<endl;
cout<<endl;
return;
}
for(int i=0;i<n;i++)
{
if(!col[i]&&!dg[i+u]&&!udg[n-u+i])
{
queen[u][i]='Q';
col[i]=dg[u+i]=udg[n-u+i]=true;
dfs(u+1);
col[i]=dg[u+i]=udg[n-u+i]=false;
queen[u][i]='.';
}
}
}
int main()
{
cin>>n;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
queen[i][j]='.';
dfs(0);
return 0;
}