力扣刷题笔记-搜索与回溯算法

搜索与回溯算法

从上到下按层打印二叉树,同一层的节点按从左到右的顺序打印,每一层打印到一行。

class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
        vector <vector <int>> ret; //动态数组
        if(!root) {
            return ret;
        }

        queue <TreeNode*> q;
        q.push(root);
        while(!q.empty()) {
            int currentLevelSize = q.size();
            ret.push_back(vector <int> ());
            for(int i=1;i<=currentLevelSize;i++) {
                auto node = q.front();
                q.pop();
                ret.back().push_back(node->val);
                if(node->left) q.push(node->left);
                if(node->right) q.push(node->right);
            }
        }
        return ret;
    }
};

这里主要涉及的是层序遍历,层序遍历主要的方法就是从上到下进行一次广度优先搜索(BFS),而BFS通常借助队列先入先出的特性实现
算法流程

  • 1.特例处理: 当根节点为空,则返回空列表 [] ;
  • 2.初始化: 打印结果列表 res = [] ,包含根节点的队列 queue = [root] ;
  • 3.BFS 循环: 当队列 queue 为空时跳出;
    • a.新建一个临时列表 tmp ,用于存储当前层打印结果;
    • b.当前层打印循环: 循环次数为当前层节点数(即队列 queue 长度);
      • 1.出队: 队首元素出队,记为 node;
      • 2.打印: 将 node.val 添加至 tmp 尾部;
      • 3.添加子节点: 若 node 的左(右)子节点不为空,则将左(右)子节点加入队列 queue ;
    • c.将当前层结果 tmp 添加入 res 。
  • 4.返回值: 返回打印结果列表 res 即可。

请实现一个函数按照之字形顺序打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右到左的顺序打印,第三行再按照从左到右的顺序打印,其他行以此类推。

class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
        vector<vector<int>> ans;
        if(!root) {
            return ans;
        }

        queue<TreeNode*> nodeQueue;
        nodeQueue.push(root);
        bool isOrderLeft = true;

        while(!nodeQueue.empty()) {
            deque<int> levelLsit;
            int size = nodeQueue.size();
            for(int i=0;i<size;i++) {
                auto node = nodeQueue.front();
                nodeQueue.pop();
                if(isOrderLeft) {
                    levelLsit.push_back(node->val);
                }else {
                    levelLsit.push_front(node->val);
                }
                if(node->left) {
                    nodeQueue.push(node->left);
                }
                if(node->right) {
                    nodeQueue.push(node->right);
                }
            }
            ans.emplace_back(vector<int>{levelLsit.begin(),levelLsit.end()});
            isOrderLeft = !isOrderLeft;
        }
        return ans;
    }
};

这里是层序遍历,但是多了一个偶数层倒序的要求。具体的实现方法是使用一个双端队列,使得在两端都可以进行插入操作,设置一个判断码来分辨奇数层和偶数层,然后使用对应的back插入和front插入方法就可以轻松实现了

输入两棵二叉树A和B,判断B是不是A的子结构。(约定空树不是任意一个树的子结构)B是A的子结构, 即 A中有出现和B相同的结构和节点值。

class Solution {
public:
    bool isSubStructure(TreeNode* A, TreeNode* B) {
        if(A == NULL || B == NULL) return false;
        if(A->val == B->val) {
            if(dfs_isEqual(A,B)) {
                return true;
            }
        }
        return isSubStructure(A->left, B) || isSubStructure(A->right, B);
    }
    bool dfs_isEqual(TreeNode* A, TreeNode* B) {
        if(B == NULL) return true;
        if(A == NULL) return false;
        if(A->val == B->val) {
            return dfs_isEqual(A->left,B->left) && dfs_isEqual(A->right,B->right);
        }else {
            return false;
        }
    }
};

首先进行树的判空处理。然后依次比较A与B的结点,采用dfs的策略进行比较。如果计较到B先为空,则说明B是A的子树;如果A先为空,则返回false,这个过程是将一直递归下去。而A的每个节点也要分别作为起始与B比较,同样采用递归实现,即A的左右子树分别与B进行比较,最终全部比较完毕。

请完成一个函数,输入一个二叉树,该函数输出它的镜像。

class Solution {
public:
    TreeNode* mirrorTree(TreeNode* root) {
        if(root == nullptr) return nullptr;
        TreeNode* left = mirrorTree(root->left);
        TreeNode* right = mirrorTree(root->right);
        root->left = right;
        root->right = left;
        return root;
    }
};

一样的事,用的是递归遍历,重点学一学递归吧,挺神奇的。

请实现一个函数,用来判断一棵二叉树是不是对称的。如果一棵二叉树和它的镜像一样,那么它是对称的。
例如,二叉树 [1,2,2,3,4,4,3] 是对称的。

class Solution {
public:
    bool check(TreeNode *p, TreeNode *q) {
        if(!p && !q) return true;
        if(!p || !q) return false;
        return p->val == q->val && check(p->left, q->right) && check(p->right, q->left);
    }
    bool isSymmetric(TreeNode* root) {
        return check(root, root);
    }
};

如果同时满足下面的条件,两个树互为镜像:

  • 它们的两个根结点具有相同的值
  • 每个树的右子树都与另一个树的左子树镜像对称

通过「同步移动」两个指针的方法来遍历这棵树,ppp 指针和 qqq 指针一开始都指向这棵树的根,随后 ppp 右移时,qqq 左移,ppp 左移时,qqq 右移。每次检查当前 ppp 和 qqq 节点的值是否相等,如果相等再判断左右子树是否对称。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值