代码随想录算法训练营第15天 |这篇文章让你一次性掌握递归和二叉树的层序遍历 LeetCode226.翻转二叉树 101. 对称二叉树 102. 二叉树的层序遍历

递归

递归的基本思想就是程序反复调用自身

如果搞不清楚递归,那大多是犯了这个错误:纠结递归本层做了什么,下一层又做了什么,导致我们把递归想的复杂化。实际上,递归是一个反复调用自身的程序,那么就说明每层递归的作用都是一样的,因此我们只需要关注一级递归的解决过程即可

那么对于一级递归,我们需要关心的主要是以下三点:

  1. 整个递归的终止条件。
  2. 这一级递归需要做什么?
  3. 应该返回给上一级的返回值是什么?

于是我们将会又这三个目标,即递归三部曲

  1. 找整个递归的终止条件:递归应该在什么时候结束?
  2. 找返回值,确定函数参数:应该给上一级返回什么信息?
  3. 本级递归应该做什么:在这一级递归中,应该完成什么任务?

下面我将拿实际题目来讲解递归 ,帮助读者更好的理解递归


226. 翻转二叉树

 本题是考查对二叉树的操作和理解的一题题目,考查了我们对二叉树三种遍历顺序(前中后序遍历)的掌握,以及我们对二叉树的递归法遍历的掌握。

1.确定递归函数的终止条件:

很显然,当节点为空时,就返回;

2.确定传入的参数和返回值:

传入的参数当然是节点,也就是TreeNode* root ,当然有的时候我们无法确定函数的参数数量,那么我们先写着,等需要的时候再补上就行

返回值类型也是TreeNode*

3.确定本层递归需要时做的事:交换两个节点的位置,这里又考查到了二叉树的前中后序遍历,我们这里如果采用前序遍历,那么单层递归的写法就是

swap(root->left, root->right);//中
invertTree(root->left);//左
invertTree(root->right);//右

那么当这三步走完之后,整体代码也就显而易见了

具体代码如下:

/**
 * 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:
    TreeNode* invertTree(TreeNode* root) {
        if(root==NULL)  return root;
        swap(root->left,root->right);
        invertTree(root->left);
        invertTree(root->right);
        return root;
    }
};


101. 对称二叉树

 那么这题题目用递归法如何解决?

还是老样子,先思考递归三部曲:

1.确定函数参数以及返回值:

函数返回值为bool型,函数参数暂时不明,也不急着确定,先放着

2.确定递归的终止条件:

那么对于这题对称二叉树而言,什么时候应该是一层递归的终止?三种节点的情况:1.左节点为空,右节点不为空  2.左节点不为空,右节点为空  3.左右节点皆为空时。还有一种节点内值的情况,如果左右节点相等,那么返回true

3.确定一层递归的逻辑:

比较二叉树两边的内侧节点是否对称

比较二叉树两边的外侧节点是否对称

如果两边都对称,那么返回true 否则返回false;本题只有使用后序遍历是能完成我上述的步骤的

那么思考完第三步,我们可以思考并确认传入的参数了,要比较二叉树两边的内侧和外侧,我们则需要一个指针和一个右指针,分别拿这两个指针来对比

所以在第一步确定函数参数时我们可以写两个参数(TreeNode* left,TreeNode* right)

具体完整代码如下:

/**
 * 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 comparison(TreeNode* left,TreeNode* right){
        确定终止条件
        if(left==NULL&&right!=NULL) return false;
        else if(left!=NULL&&right==NULL) return false;
        else if(left==NULL&&right==NULL)    return true;
        else if(left->val!=right->val)  return false;
        单层逻辑
        return comparison(left->left,right->right)&&comparison(left->right,right->left);

    }
    bool isSymmetric(TreeNode* root) {
        if(root==NULL)  return true;
        return comparison(root->left,root->right);
    }
};

 看完了上面两个题目,相信大家对递归也有了一定的理解,下面我来讲二叉树的层序遍历:

二叉树的层序遍历:


102. 二叉树的层序遍历

层序遍历,就是BFS,逐层的遍历二叉树

对于层序遍历,我们可以使用队列这一数据结构,利用他先进后出的特点,来层序遍历二叉树

具体代码如下

/**
 * 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:
    vector<vector<int>> levelOrder(TreeNode* root) {
        vector<vector<int>>result;
        queue<TreeNode*>que;
        if(root!=NULL) que.push(root);
        while(!que.empty()){
            int size=que.size();
            vector<int>vec;
            for(int i=0;i<size;i++){
                TreeNode* node=que.front();
                que.pop();
                vec.push_back(node->val);
                if (node->left) que.push(node->left);
                if (node->right) que.push(node->right);
            }
            result.push_back(vec);
        }
        return result;
    }

};

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值