DAY17|二叉树part2

层序遍历

一个打十个!

102 二叉树的层序遍历

/**
 * 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;
        if(root==nullptr) return result;
        queue<TreeNode*> q;
        q.push(root);
        while(q.empty()==0){
            int size=q.size();
            vector<int> each;
            while(size--){
                TreeNode* t=q.front();
                each.push_back(t->val);
                q.pop();
                if(t->left!=nullptr) q.push(t->left);
                if(t->right!=nullptr) q.push(t->right);
            }
            result.push_back(each);
        }
        return result;
    }
};

107. 二叉树的层序遍历II

具体思路就是在上一题的基础上把result的数组利用双指针翻转过来。

/**
 * 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>> levelOrderBottom(TreeNode* root) {
        vector<vector<int>> result;
        if(root==nullptr) return result;
        queue<TreeNode*> q;
        q.push(root);
        while(q.empty()==0){
            int size=q.size();
            vector<int> each;
            while(size--){
                TreeNode* t=q.front();
                each.push_back(t->val);
                q.pop();
                if(t->left!=nullptr) q.push(t->left);
                if(t->right!=nullptr) q.push(t->right);
            }
            result.push_back(each);
        }
        int n=result.size();//数组个数
        int left=0,right=n-1;
        while(left<right){
            vector<int> p=result[left];
            result[left]=result[right];
            result[right]=p;
            ++left;
            --right;
        }
        return result;
    }
    
};

199 二叉树的右视图

也是层序遍历,返回遍历后的每一层的最后一个元素

/**
 * 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<int> rightSideView(TreeNode* root) {
        vector<int> result;
        if (root == nullptr)
            return result;

        queue<TreeNode*> q;
        q.push(root);
        while (q.empty() != 1) {
            int size=q.size();
            int rightest;
            while(size--){
                TreeNode* t=q.front();
                rightest=t->val;
                q.pop();
                if(t->left != nullptr) q.push(t->left);
                if(t->right != nullptr) q.push(t->right);
            }
            result.push_back(rightest);
        }
        return result;
    }
};

其实我这里没写判断目前元素是否为该层最后一个元素的语句。我只是在每层内进行遍历的时候,每次都将当前元素的val存入rightest变量,不停覆盖,直到最后一个元素结束后跳出当前层的循环,此时rightest没有被覆盖,就直接是当前层的最后一个元素,此时直接存入result数组即可。

637.二叉树的层平均值

注意两个点:第一个是在计算每层之和的时候需要使用Long int不然会溢出。
第二个是在最后求均值的时候,定义了一个double型变量,但是不能直接把sum/n赋值给此变量,不然得到的还是Int型数,应该先把总和赋给double型变量,然后用这个double来除以n求平均值,得到的才能是double。

/**
 * 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<double> averageOfLevels(TreeNode* root) {
        vector<double> result;
        if(root==nullptr) return result;
        queue <TreeNode*> q;
        q.push(root);
        while(q.empty()==0){
            int size=q.size();
            int n=size;
            long int sum=0;
            while(size--){
                TreeNode* t=q.front();
                sum+= t->val;
                q.pop();
                if(t->left!=nullptr) q.push(t->left);
                if(t->right!=nullptr) q.push(t->right);
            }
            double each =sum;
            each=each/n;
            result.push_back(each);
        }
        return result;
    }
};

429. N 叉树的层序遍历

和二叉树层序遍历也没有啥不同

/*
// Definition for a Node.
class Node {
public:
    int val;
    vector<Node*> children;

    Node() {}

    Node(int _val) {
        val = _val;
    }

    Node(int _val, vector<Node*> _children) {
        val = _val;
        children = _children;
    }
};
*/

class Solution {
public:
    vector<vector<int>> levelOrder(Node* root) {
        vector<vector<int>> result;
        if(root==nullptr) return result;
        queue<Node*> q;
        q.push(root);
        while(q.empty()==0){
            int size=q.size();
            vector<int> each;
            while(size--){
                Node* t=q.front();
                each.push_back(t->val);
                q.pop();
                vector<Node*> ch=t->children;
                int n=ch.size();
                for(int i=0;i<n;++i){
                    q.push(ch[i]);
                }
            }
            result.push_back(each);
        }
        return result;
    }
};

515. 在每个树行中找最大值

用模板写。。真的又快又简单。。。

/**
 * 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<int> largestValues(TreeNode* root) {
        vector<int> result;
        if(root==nullptr) return result;
        queue <TreeNode*> myQue;
        myQue.push(root);
        while(myQue.empty()==0){
            int size=myQue.size();
            int M=INT_MIN;
            while(size--){
                TreeNode* t=myQue.front();
                M=max(M,t->val);
                myQue.pop();
                if(t->left) myQue.push(t->left);
                if(t->right) myQue.push(t->right);
            }
            result.push_back(M);
        }
        return result;
    }
};

116. 填充每个节点的下一个右侧节点指针

/*
// Definition for a Node.
class Node {
public:
    int val;
    Node* left;
    Node* right;
    Node* next;

    Node() : val(0), left(NULL), right(NULL), next(NULL) {}

    Node(int _val) : val(_val), left(NULL), right(NULL), next(NULL) {}

    Node(int _val, Node* _left, Node* _right, Node* _next)
        : val(_val), left(_left), right(_right), next(_next) {}
};
*/

class Solution {
public:
    Node* connect(Node* root) {
        if(root==NULL) return root;
        queue<Node*> myque;
        myque.push(root);
        while(myque.empty()==0){
            int size=myque.size();
            Node* prev;
            Node* curr;
            for(int i=0;i<size;++i){
                
                if(i==0){
                    prev=myque.front();
                    myque.pop();
                    if(prev->left) myque.push(prev->left);
                    if(prev->right) myque.push(prev->right);
                }
                else{
                    curr=myque.front();
                    myque.pop();
                    if(curr->left) myque.push(curr->left);
                    if(curr->right) myque.push(curr->right);
                    prev->next=curr;
                    prev=curr;
                }
            }
            prev->next=NULL;
        }
        return root;
    }
};

相比正常的层序遍历方法有一点点绕,因为要考虑是否为本层第一个节点。之前在每层遍历的时候我喜欢直接用while(size–),这里用for循环会更容易判断是否为本层第一个节点。

117. 填充每个节点的下一个右侧节点指针 II

和上一道题一模一样的代码。。。完全没区别直接复制粘贴也能AC。
略了。

104.二叉树的最大深度

简简单单层序遍历,计个层数就行。

/**
 * 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:
    int maxDepth(TreeNode* root) {
        int result=0;
        if(root==nullptr) return result;
        queue<TreeNode*> myque;
        myque.push(root);
        while(myque.empty()==0){
            int size=myque.size();
            result++;
            while(size--){
                TreeNode* t=myque.front();
                myque.pop();
                if(t->left) 
                    myque.push(t->left);
                if(t->right) 
                    myque.push(t->right);
            }
        }
        return result;
    }
};

111. 二叉树的最小深度

/**
 * 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:
    int minDepth(TreeNode* root) {
        int result=0;
        if(root==nullptr) return result;
        queue<TreeNode*> myque;
        myque.push(root);
        while(myque.empty()==0){
            int size=myque.size();
            result++;
            while(size--){
                TreeNode* t=myque.front();
                if(t->left==nullptr && t->right==nullptr) return result;
                myque.pop();
                if(t->left) myque.push(t->left);
                if(t->right) myque.push(t->right);
            }
        }
        return result;
    }
};

有点点绕,本质还是层序遍历,在遍历每层的时候找本层是否存在叶节点,若存在则直接返回当前层数。

层序遍历的十道题刷完了,会了模板以后真的又简单又快,库库就是一顿写啊。

226. 翻转二叉树

也许可以层序遍历每个节点,然后交换每个节点的左右子节点?
让我来试一下:

/**
 * 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==nullptr) return root;
        queue<TreeNode*> myque;
        myque.push(root);
        while(myque.empty()==0){
            int size=myque.size();
            while(size--){
                TreeNode* t=myque.front();
                myque.pop();
                TreeNode* help=t->left;
                t->left=t->right;
                t->right=help;
                if(t->left) myque.push(t->left);
                if(t->right) myque.push(t->right);
            }
        }
        return root;
    }
};

可以AC。
看了题解:
这道题使用前序后序遍历也可以,(中序遍历不可以因为会把某些节点翻转两次),层序遍历也可以实现

二叉树解题的大忌就是自己稀里糊涂的过了(因为这道题相对简单),但是也不知道自己是怎么遍历的。

再试试深度优先遍历的非递归和递归方法来实现这道题:
递归方法的前序遍历:

/**
 * 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) {
        process(root);
        return root;
    }
    void process(TreeNode* root){
        if(root==nullptr) return;
        TreeNode* t=root->left;
        root->left=root->right;
        root->right=t;
        process(root->left);
        process(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==nullptr) return root;
        stack<TreeNode*> myst;
        myst.push(root);
        while(myst.empty()==0){
            TreeNode* t=myst.top();
            myst.pop();
            TreeNode* a=t->left;
            t->left=t->right;
            t->right=a;
            if(t->right) myst.push(t->right);
            if(t->left) myst.push(t->left);
        }
        return root;
    }
};

odk, 下一题

101 对称二叉树

没什么思路。。
看题解:
其实本质是看头节点下面左右节点的二叉树是否为对方的翻转版本。
写一个递归分别遍历两个二叉树,遍历的时候比较左树外侧和右树外侧,左树内侧和右树内侧的节点是否相等即可

/**
 * 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 isSymmetric(TreeNode* root) {
        bool result=true;
        if(root==nullptr) return result;
        process(root->right,root->left,result);
        return result;
    }
    void process(TreeNode* right, TreeNode* left, bool& result){
        if(left==nullptr && right==nullptr) return;
        if(left==nullptr && right!=nullptr) {
            result=false;
            return;
        }
        if(right==nullptr&& left!=nullptr){
            result=false;
            return;
        }
        if(right->val != left->val){
            result=false;
            return;
        }
        process(right->right,left->left,result);

        process(left->right,right->left,result);
    }
};

非递归版本:

/**
 * 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 isSymmetric(TreeNode* root) {
        //bool result;
        if(root==nullptr) return true;
        if(root->left==nullptr && root->right!=nullptr) return false;
        if(root->right==nullptr && root->left != nullptr) return false;
        if(root->left==nullptr&& root->right==nullptr) return true;
        queue<TreeNode*> myque;
        myque.push(root->left);
        myque.push(root->right);
        while(myque.empty()==0){
            int size=myque.size();
            if(size%2) return false;
            for(int i=0;i<size;++i){
                TreeNode* a=myque.front();
                myque.pop();
                TreeNode* b=myque.front();
                myque.pop();
                ++i;
                if(a==nullptr&&b!=nullptr) return false;
                if(a!=nullptr&&b==nullptr) return false;
                if(a==nullptr&&b==nullptr) continue;
                if(a->val !=b->val) return false;
                myque.push(a->left);
                myque.push(b->right);
                myque.push(a->right);
                myque.push(b->left);
            }
        }
        return true;
    }
};

用队列,把左右子树对应的节点依次存入队列,一次弹出两个进行比对,而且是按层比对,但跟层序遍历入队列的顺序不太相同。

DAY17的内容完事,看了一下对二叉树的周末小结:

在实现迭代法的过程中,有同学问了:递归与迭代究竟谁优谁劣呢?

从时间复杂度上其实迭代法和递归法差不多(在不考虑函数调用开销和函数调用产生的堆栈开销),但是空间复杂度上,递归开销会大一些,因为递归需要系统堆栈存参数返回值等等。

递归更容易让程序员理解,但收敛不好,容易栈溢出。
这么说吧,递归是方便了程序员,难为了机器(各种保存参数,各种进栈出栈)。
在实际项目开发的过程中我们是要尽量避免递归!因为项目代码参数、调用关系都比较复杂,不容易控制递归深度,甚至会栈溢出。


over!

  • 25
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值