第101题,给定一个二叉树,检查它是否是镜像对称的。
递归法:
根据题目的描述,镜像对称,就是左右两边相等,也就是左子树和右子树是相当的。
注意这句话,左子树和右子相等,也就是说要递归的比较左子树和右子树。
我们将根节点的左子树记做 left,右子树记做 right。比较 left 是否等于 right,不等的话直接返回就可以了。
如果相当,比较 left 的左节点和 right 的右节点,再比较 left 的右节点和 right 的左节点。
因此递归函数应当传入两个参数,即两个相等的结点各自的左节点和右节点。
如果这两个节点都为空,相等;
一方为空,不等;
只想等,递归判断a->left, b->right和a->right, b->left是否相等
bool IsSym(struct TreeNode* a,struct TreeNode* b)
{
if(!a && !b)
return true;
if( (!a && b) || (a && !b) )
return false;
return a->val == b->val && IsSym(a->left, b->right) && IsSym(a->right, b->left);
}
bool isSymmetric(struct TreeNode* root){
if(!root)
return true;
return IsSym(root->left, root->right);
}
迭代解法:
利用队列辅助实现,可以为根结点的左子树和右子树各准备一个队列:
q1和q2,每个队列一队首尾指针,当首指针小于尾指针时,继续扫描。
首先根结点入队,首指针每次扫描一个元素,当两个队列的同一组元素相等时,尾指针向后扫描该元素的左右结点入队,注意如果相同的元素为null,尾指针不向后扫描。
#define QUEUESIZE 2000
bool isSymmetric(struct TreeNode* root){
if(!root)
return true;
if(!root->left && !root->right)
return true;
if(!root->left || !root->right)
return false;
struct TreeNode* q1[QUEUESIZE];
struct TreeNode* q2[QUEUESIZE];
int front1, rear1, front2, rear2;
front1 = rear1 = front2 = rear2 = -1;
q1[++rear1] = root->left;
q2[++rear2] = root->right;
struct TreeNode *a, *b;
while(front1 < rear1){
a = q1[++front1];
b = q2[++front2];
if(!a && !b)
continue;
if(!a || !b)
return false;
if(a->val != b->val)
return false;
q1[++rear1] = a->left;
q2[++rear2] = b->right;
q1[++rear1] = a->right;
q2[++rear2] = b->left;
}
return true;
}
也可以使用一个队列,此时每次循环尾指针移动四个位置(未出现相等元素为null的情况),首指针每次循环移动两个位置。
bool isSymmetric(struct TreeNode* root){
if (root == NULL) {
return true;
}
struct TreeNode *node[QUEUESIZE];
int rear = 0;
node[rear++] = root->left;
node[rear++] = root->right;
int front = 0;
while(front < rear) {
if (node[front] == NULL && node[front + 1] == NULL) {
front += 2;
continue;
}
if (node[front] == NULL || node[front + 1] == NULL) {
return false;
}
if (node[front]->val != node[front + 1]->val) {
return false;
}
node[rear++] = node[front]->left;
node[rear++] = node[front + 1]->right;
node[rear++] = node[front]->right;
node[rear++] = node[front + 1]->left;
front += 2;
}
return true;
}
第100题 相同的树
还是递归和队列迭代两种方法:
先上递归,两个结点都空,返回true;有且只有一个空,返回false;结点值不一样返回false;以上都不满足时同时递归左右子树。
bool isSameTree(struct TreeNode* p, struct TreeNode* q){
if(!p&&!q) return true;
if(!p||!q) return false;
if(p->val!=q->val) return false;
return isSameTree(p->left, q->left) && isSameTree(p->right, q->right);
}
建立队列,进行递归。还是设立两个队列,两对首尾指针,为防止出现队列大小不够,采用循环队列的方式。
#define maxsize 100
bool isSameTree(struct TreeNode* p, struct TreeNode* q){
struct TreeNode *queue1[maxsize];
struct TreeNode *queue2[maxsize];
int front1=0; int front2=0; int rear1=0; int rear2=0;
queue1[rear1] = p;
queue2[rear2] = q;
rear1=(rear1+1)%maxsize;
rear2=(rear2+1)%maxsize;//循环队列
while(rear1!=front1||rear2!=front2)//队空判断(中间是或(||)而不是与(&&))
{//因为层序遍历是逐层的,比如测试用例的1 2 3 ,假如q数的2有左子树,p树的2没有左子树, //那么结果将会是返回true,与事实不符。自己画图尝试!
p=queue1[front1];front1=(front1+1)%maxsize;
q=queue2[front2];front2=(front2+1)%maxsize;//出队
if(!p&&!q) return true;
if(!p||!q) return false;
if(p->val!=q->val) return false;
// 若if语句没有执行,那就正常的层序遍历那样入队,出队,知道全部都相等
if(p->left||q->left)
{
queue1[rear1]=p->left;
queue2[rear2]=q->left;
rear1=(rear1+1)%maxsize;
rear2=(rear2+1)%maxsize;
}
if(p->right||q->right)
{
queue1[rear1]=p->right;
queue2[rear2]=q->right;
rear1=(rear1+1)%maxsize;
rear2=(rear2+1)%maxsize;
}
}
return true;
}