leetcode刷题笔记(三)

第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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值