记录一下leetcode刷题(6)

面试题32 - I. 从上到下打印二叉树

描述

从上到下打印出二叉树的每个节点,同一层的节点按照从左到右的顺序打印。
例如:
输入
给定二叉树:
[3,9,20,null,null,15,7],
     ~~~~        ~   3
     ~~~~      /      ~~~~     \
     ~~~~      9   ~   20
     ~~~~            ~~~~~      / \
     ~~~~        ~   15   ~   7
输出:[3,9,20,15,7]
   ~~   
条件节点总数 <= 1000

思路

从头结点开始层次遍历二叉树,用一个队列存储每一个不为null的节点,每一层的子节点存在当前层节点的后面,先进先出,用数组(使用vector动态数组,不用考虑数值个数)存储每个不为null节点的数值。

代码

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    vector<int> levelOrder(TreeNode* root) {
        vector<int> tree;
        queue<TreeNode*> q;
        if(root==NULL) return {};
        q.push(root);
        while(!q.empty()){
            TreeNode* p=q.front();//取队列树头节点
            if(p->left!=NULL) q.push(p->left);
            if(p->right!=NULL) q.push(p->right);//将此节点的左右不为空的子树放到队列里
            q.pop();
            tree.push_back(p->val);
        }
        return tree;
    }
};
/*
执行用时:0ms;
内存消耗:11.9.
*/

剑指 Offer 32 - II. 从上到下打印二叉树 II

描述

从上到下按层打印二叉树,同一层的节点按从左到右的顺序打印,每一层打印到一行。
例如:
给定二叉树:
[3,9,20,null,null,15,7],
     ~~~~        ~   3
     ~~~~      /      ~~~~     \
     ~~~~      9   ~   20
     ~~~~            ~~~~~      / \
     ~~~~        ~   15   ~   7
返回其层次遍历结果:
[
[3],
[9,20],
[15,7]
]

思路

整体思路同上一题,不过在每一层遍历的时候多了一层循环,在上一层遍历结束时,记录当前队列数量(当前层个数),再新建一个单层的数组用来存储当前层的数值,一层循环结束后,将该数组存入需要输出的数组。

代码

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
        vector<vector<int>> tree;
        vector<int> brant;
        if(root==NULL)
        return {};
        queue<TreeNode*>q;
        q.push(root);
        while(!q.empty()){
            TreeNode* p;     
            int x=q.size();
            brant.clear();
            for(int i=0;i<x;i++){
                p=q.front();
                if(p->left!=NULL) q.push(p->left);
                if(p->right!=NULL) q.push(p->right);
                q.pop();
                brant.push_back(p->val);
            }
            tree.push_back(brant);
        }
        return tree;

    }
};
/*
执行用时:8ms;
内存消耗:12.3。
*/

剑指 Offer 32 - III. 从上到下打印二叉树 III

描述

请实现一个函数按照之字形顺序打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右到左的顺序打印,第三行再按照从左到右的顺序打印,其他行以此类推。
例如:
给定二叉树:
[3,9,20,null,null,15,7],
     ~~~~        ~   3
     ~~~~      /      ~~~~     \
     ~~~~      9   ~   20
     ~~~~            ~~~~~      / \
     ~~~~        ~   15   ~   7
返回其层次遍历结果:
[
[3],
[20,9],
[15,7]
]

思路

整体思路依旧跟上一题一致,唯一的区别在于我用了一个变量记录层数,从0开始记录,当遍历的层数为奇数时,就用一个栈做辅助实现当前层数组的倒序,再将当前层倒序后的数组收入结果数组。

代码

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
        vector<vector<int>> tree;
        vector<int> brant;
        if(root==NULL)
        return {};
        queue<TreeNode*>q;
        q.push(root);
        int y=0;
        while(!q.empty()){
            TreeNode* p;     
            int x=q.size();
            brant.clear();
            for(int i=0;i<x;i++){
                p=q.front();
                if(p->left!=NULL) q.push(p->left);
                if(p->right!=NULL) q.push(p->right);
                q.pop();
                brant.push_back(p->val);
            }
            if(y%2==1){
                stack<int>brant2;
                for(int i=0;i<x;i++){
                    brant2.push(brant[i]);
                }
                brant.clear();
                for(int i=0;i<x;i++){
                    brant.push_back(brant2.top());
                    brant2.pop();
                }
            }
            tree.push_back(brant);
            y++;
        }
        return tree;
    }
};
/*
执行用时:4ms;
内存消耗:12.7MB。
*/

剑指 Offer 26. 树的子结构

描述

输入两棵二叉树A和B,判断B是不是A的子结构。(约定空树不是任意一个树的子结构)
B是A的子结构, 即 A中有出现和B相同的结构和节点值。
例如:
给定的树 A:
     ~~~~        ~   3
     ~~~~      /      ~~~~     \
     ~~~~      4   ~   5
     ~~~~      / \
   ~~    1   ~   2
给定的树 B:
     ~~~~      4
     ~~~~      /
   ~~    1   ~  
返回 true,因为 B 与 A 的一个子树拥有相同的结构和节点值。
   ~~   
示例 1
输入:A = [1,2,3], B = [3,1]
输出:false
示例 2
输入:A = [3,4,5,1,2], B = [4,1]
输出:true
限制0 <= 节点个数 <= 10000

思路

核心思想是利用两次循环。
第一次是遍历A树的节点,用B树的头结点与其比较,找到符合要求的子树头结点。采用递归的手段,父节点不符合,就看子节点符不符合,只要有一个符合即可。
待找到后,进行第二次循环,这次的循环是比较B的结构是否在A当中,也用递归的手段,若是头结点值相等,就再判断左孩子以及右孩子的结构相不相等(看B树有没有孩子,有则比较,没有就默认这部分相等)。第二个循环也单独写了个函数调用。

代码

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:

    //当输入的树的头结点跟大树某个结点值相等,判断子树结构是否相等
    bool issame(TreeNode* A,TreeNode* B)
    {
        if(B==NULL) return true;//子树遍历结束,前面元素都相等
        if(A==NULL) return false;//大树遍历结束,子树还没结束,子树超数
        if(A->val!=B->val)//有元素不相等,则不是
            return false;     
        return issame(A->left,B->left)&&issame(A->right,B->right);
    }
    bool isSubStructure(TreeNode* A, TreeNode* B) //判断子树是否存在
    {
        if(A==NULL||B==NULL)//都是空树不存在
            return false;
        else if(A->val==B->val&&issame(A,B))//当头结点相等且子树结构相等
            return true;
        //头结点不相等时,去找大树的子节点
        return isSubStructure(A->left,B)||isSubStructure(A->right,B);
    }
    
};
/*
执行用时:28ms;
消耗内存:32.9MB。
*/

剑指 Offer 27. 二叉树的镜像

描述

请完成一个函数,输入一个二叉树,该函数输出它的镜像。
例如输入:
     ~~~~        ~   4
     ~~~~      /      ~~~~     \
    ~~~     2     ~~~     7
   ~~    / \     ~~~    / \
  ~   1 3   ~   6 9
镜像输出:
     ~~~~        ~   4
     ~~~~      /      ~~~~     \
    ~~~     7     ~~~     2
   ~~    / \     ~~~    / \
  ~   9 6   ~   3 1
**示例 **:
输入:root = [4,2,7,1,3,6,9]
输出:[4,7,2,9,6,3,1]
限制0 <= 节点个数 <= 1000

思路

利用递归函数,直接修改二叉树,调换每个节点的左右节点,同时调换的还是镜像过的左右节点。

代码

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* mirrorTree(TreeNode* root) {
        if(root==NULL)
            return root;
        TreeNode* p=root->left;   
        root->left=mirrorTree(root->right);
        root->right=mirrorTree(p);
        return root;
    }
};
/*
执行用时:0ms;
内存消耗:9MB。
*/

剑指 Offer 28. 对称的二叉树

描述

请实现一个函数,用来判断一棵二叉树是不是对称的。如果一棵二叉树和它的镜像一样,那么它是对称的。
例如,二叉树 [1,2,2,3,4,4,3] 是对称的。
     ~~~~        ~   1
     ~~~~      /      ~~~~     \
    ~~~     2     ~~~     2
   ~~    / \     ~~~    / \
  ~   3 4   ~   4 3
但是下面这个 [1,2,2,null,3,null,3] 则不是镜像对称的:
     ~~~~        ~   1
     ~~~~      /      ~~~~     \
    ~~~     2     ~~~     2
     ~~~~      \      ~~~~      \
     ~~~~      3      ~~~~      3
示例 1
输入:root = [1,2,2,3,4,4,3]
输出:true
示例 2
输入:root = [1,2,2,null,3,null,3]
输出:false
限制0 <= 节点个数 <= 1000

思路

首先分析一下对称树的样子。
空树或者只有一层的话,一定是对称树;
从二层往下,每层必须满足左右对称,如果把null的位置填充为一个默认值(我用的-99),然后参考打印二叉树的做法,把每一层存到一个数组里,数组大小一定是偶数,再设置一个判断该数组元素是否左右对称的函数,每遍历一层就判断一次,一旦不对称,则不是对称二叉树,若每一层都左右对称,则该树是对称二叉树。

代码

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    bool isdui(vector<int> link){
        int x=link.size()/2;
        for(int i=0;i<x;i++){
            if(link[i]!=link[2*x-1-i])
                return false;
        }
        return true;
    }
    bool isSymmetric(TreeNode* root) 
    {
        if(root==NULL) return true;//空树一定为对称
        if(root->left==NULL&&root->right==NULL) return true;//只有头结点
        if(root->left==NULL||root->right==NULL) return false;//有一边没有
        if(root->left->val!=root->right->val) return false;//第二层两个不一样一定不对称
        //从第三行开始,一行一行看是否对称,有缺失就补全,我用的-99
        vector<int> brant;
        queue<TreeNode*>q;
        q.push(root->left);
        q.push(root->right);
        while(!q.empty())
        {
            TreeNode* p;     
            int y=q.size();
            brant.clear();
            for(int i=0;i<y;i++)
            {
                p=q.front();
                if(p->left!=NULL){
                    q.push(p->left);
                    brant.push_back(p->left->val);
                }
                else
                    brant.push_back(-99);
                if(p->right!=NULL){
                    q.push(p->right); 
                    brant.push_back(p->right->val);
                }           
                else
                    brant.push_back(-99);
                q.pop();
            }
            if(!isdui(brant)) return false;
        }
        return true;
    }
    
};
/*
执行用时:4ms;
内存消耗:16.2MB。
*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值