代码随想录算法训练营第18天-层序遍历10道题-226.翻转二叉树-101. 对称二叉树

层序遍历十道题

层序遍历其实很简单,用一个队列很容易就能实现

102. 二叉树的层序遍历

这道题目要求逐层范围,因此别忘了在每层开始前记录一下当前队列的大小,作为弹出结点的个数

vector<vector<int>> levelOrder(TreeNode* root) {
    vector<vector<int>> res;
    queue<TreeNode*> q;

    if (root) q.push(root);
    while (!q.empty())
    {
        int size = q.size();
        vector<int> vec;
        while (size--)
        {
            TreeNode* cur = q.front();
            q.pop();
            if (cur->left) q.push(cur->left);
            if (cur->right) q.push(cur->right);

            vec.push_back(cur->val);
        }
        res.push_back(vec);
    }
    return res;
}

107.二叉树的层次遍历 II

比那个多个翻转

vector<vector<int>> levelOrderBottom(TreeNode* root) {
    vector<vector<int>> res;
    queue<TreeNode*> q;

    if (root) q.push(root);
    while (!q.empty())
    {
        int size = q.size();
        vector<int> vec;

        while (size--)
        {
            TreeNode* cur = q.front();
            q.pop();

            if (cur->left) q.push(cur->left);
            if (cur->right) q.push(cur->right);

            vec.push_back(cur->val);
        }

        res.push_back(vec);
    }

    reverse(res.begin(), res.end());
    return res;
}

199.二叉树的右视图

稍微修改一下,层序改从右向左,每次都把第一个先放进res

vector<int> rightSideView(TreeNode* root) {
    vector<int> res;
    queue<TreeNode*> q;

    if (root) q.push(root);
    while (!q.empty())
    {
        int size = q.size();

        res.push_back(q.front()->val);

        while (size--)
        {
            TreeNode* cur = q.front();
            q.pop();

            if (cur->right) q.push(cur->right);
            if (cur->left) q.push(cur->left);
        }
    }

    return res;
}

637.二叉树的层平均值

vector<double> averageOfLevels(TreeNode* root) {
    vector<double> res;
    queue<TreeNode*> q;

    if (root) q.push(root);
    while (!q.empty())
    {
        int size = q.size();
        double sum = 0;

        for (int i = 0; i < size; i++)
        {
            TreeNode* cur = q.front();
            q.pop();

            sum += cur->val;

            if (cur->left) q.push(cur->left);
            if (cur->right) q.push(cur->right);
        }

        res.push_back(sum / size);
    }
    return res;

}

429.N叉树的层序遍历

vector<vector<int>> levelOrder(Node* root) {
    vector<vector<int>> res;
    queue<Node*> q;

    if (root) q.push(root);
    while (!q.empty())
    {
        int size = q.size();
        vector<int> vec;
        while (size--)
        {
            Node* cur = q.front();
            q.pop();

            for (auto& x : cur->children) q.push(x);

            vec.push_back(cur->val);
        }
        res.push_back(vec);
    }
    return res;
}

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

vector<int> largestValues(TreeNode* root) {
    vector<int> res;
    queue<TreeNode*> q;

    if (root) q.push(root);
    while (!q.empty())
    {
        int size = q.size();
        int maxNum = INT_MIN;
        while (size--)
        {
            TreeNode* cur = q.front();
            q.pop();

            if (cur->left) q.push(cur->left);
            if (cur->right) q.push(cur->right);

            maxNum = max(maxNum, cur->val);
        }
        res.push_back(maxNum);
    }
    return res;
}

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

Node* connect(Node* root) {
    queue<Node*> q;

    if (root) q.push(root);
    while (!q.empty())
    {
        int size = q.size();
        // cout << size << endl;

        for (int i = 0; i < size; i++)
        {
            Node* cur = q.front();
            q.pop();

            if (cur->left) q.push(cur->left);
            if (cur->right) q.push(cur->right);

            if (i == size - 1) cur->next = nullptr;
            else cur->next = q.front();
        }
    }
    return root;
}

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

同116

104.二叉树的最大深度

1.层序遍历

int maxDepth(TreeNode* root) {
    int depth = 0;
    queue<TreeNode*> q;

    if (root) q.push(root);
    while (!q.empty())
    {
        depth++;

        int size = q.size();
        while (size--)
        {
            TreeNode* cur = q.front();
            q.pop();

            if (cur->left) q.push(cur->left);
            if (cur->right) q.push(cur->right);
        }
    }
    return depth;
}

2.递归

显然,深度等于 max(左子树深度,右子树深度) + 1

int maxDepth(TreeNode* root) {
    if (root == nullptr) return 0;

    return max(maxDepth(root->left), maxDepth(root->right)) + 1;
}

111.二叉树的最小深度

1.层序

int minDepth(TreeNode* root) {
    int depth = 0;
    queue<TreeNode*> q;

    if (root) q.push(root);
    while (!q.empty())
    {
        depth++;

        int size = q.size();
        while (size--)
        {
            TreeNode* cur = q.front();
            q.pop();

            if (cur->left) q.push(cur->left);
            if (cur->right) q.push(cur->right);

            if (cur->left == nullptr && cur->right == nullptr) 
            return depth;
        }
    }
    return depth;
}

2.递归

int minDepth(TreeNode* root) {
    if (root == nullptr) return 0;
    if (root->left == nullptr && root->right == nullptr) return 1;

    if (root->left == nullptr) return minDepth(root->right) + 1; 
    if (root->right == nullptr) return minDepth(root->left) + 1; 

    return min(minDepth(root->left), minDepth(root->right)) + 1;
}

226.翻转二叉树

从此开始,我们就是使用几种遍历的题目了

这个题目就是把每个结点都左右翻一下,可以的方法很多,但是一定要搞清翻转的次数,别翻了又翻回去。

我们可以遍历每个结点,然后让它的两个子结点翻转。

对于前中后序遍历,层序遍历,我们可以将原本的打印换成别的工作,来实现一些功能

1.前、后序翻转(递归)

前序和后序都可以,但是中序不行,中序翻转的子树是同一个(其实也不是不行,只不过就是两次invert都是左子树,因为后一次的左实际上是原本的右,写题还是不能太机械)

TreeNode* invertTree(TreeNode* root) {
    //翻转左子树,翻转右子树,左右翻转
    if (root == nullptr) return nullptr;
	
    //左、右、中,因此这是后序
    invertTree(root->left);
    invertTree(root->right);

    swap(root->left, root->right);

    return root;
}

2.利用遍历翻转

既然前序后序可以,自然我们可以用迭代版本

TreeNode* invertTree(TreeNode* root) {
    stack<TreeNode*> st;

    if (root) st.push(root);
    while (!st.empty())
    {
        TreeNode* cur = st.top();
        st.pop();

        if (cur->right) st.push(cur->right);
        if (cur->left) st.push(cur->left);

        swap(cur->left, cur->right);
    }

    return root;
}

3.层序遍历

层序遍历实际也可以,只不过还是注意先入队列后翻转

TreeNode* invertTree(TreeNode* root) {
    queue<TreeNode*> q;

    if (root) q.push(root);
    while (!q.empty())
    {
        int size = q.size();

        while (size--)
        {
            TreeNode* cur = q.front();
            q.pop();

            if (cur->left) q.push(cur->left);
            if (cur->right) q.push(cur->right);

            swap(cur->left, cur->right);
        }
    }
    return root;
}

4.统一迭代法

这个是为了复习统一迭代法,所以我们写一下

统一迭代法不受遍历方法影响,因为访问一定在处理前,而访问时已经将结点入栈了,即便翻转了也不影响处理顺序

TreeNode* invertTree(TreeNode* root) {
    stack<TreeNode*> st;

    if (root) st.push(root);
    while(!st.empty())
    {
        TreeNode* cur = st.top();
        st.pop();
        if (cur)
        {
            //以中序为例
            if (cur->right) st.push(cur->right);

            st.push(cur);
            st.push(nullptr);

            if (cur->left) st.push(cur->left);
        }
        else
        {
            cur = st.top();
            st.pop();

            swap(cur->left, cur->right);
        }
    }
    return root;
}

101. 对称二叉树

1.自己想的,用前序和翻转的前序对比

bool isSymmetric(TreeNode* root) {
    //以中左右和中右左顺序遍历,检测是否一样
    stack<TreeNode*> st1;
    stack<TreeNode*> st2;

    if (root) { st1.push(root);st2.push(root); }
    while (!st1.empty() && !st2.empty())
    {
        TreeNode* cur1 = st1.top();
        TreeNode* cur2 = st2.top();
        st1.pop();
        st2.pop();

        if (cur1->val != cur2->val) return false;

        if (cur1->left && cur2->right) { st1.push(cur1->left); st2.push(cur2->right); }
        else if (!cur1->left && !cur2->right) { }
        else return false;

        if (cur1->right && cur2->left) { st1.push(cur1->right); st2.push(cur2->left); }
        else if (!cur1->right && !cur2->left) { }
        else return false; 

    }
    return st1.empty() && st2.empty();
}

2.递归

bool compare(TreeNode* left, TreeNode* right)
{
    if (left == nullptr && right == nullptr) return true;
    else if (left != nullptr && right == nullptr) return false;
    else if (left == nullptr && right != nullptr) return false;
    else if (left->val != right->val) return false;

    return compare(left->left, right->right) && compare(left->right, right->left);
}

bool isSymmetric(TreeNode* root) {
    return compare(root->left, root->right);
}

3.使用队列,成对放入比较(类似层序遍历)

其实换成栈也可以,只要是成对成对比就行。(用栈的话就是上一层从外往里,这一层从里往外,不影响)

bool isSymmetric(TreeNode* root) {
    queue<TreeNode*> q;

    if (root) { q.push(root->left);q.push(root->right); }
    while (!q.empty())
    {
        TreeNode* l = q.front();q.pop();
        TreeNode* r = q.front();q.pop();

        //两个对称位置的节点只有存在和不存在
        if (l == nullptr && r == nullptr) continue;

        if (!l || !r || l->val != r->val) return false;

        q.push(l->left);
        q.push(r->right);
        q.push(l->right);
        q.push(r->left);
    }
    return true;
}
  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

去人777

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值