Day15 二叉树 层序遍历 LeetCode 226 101 102

88 阅读3分钟

102. 二叉树的层序遍历

心得

  • 采用队列,来进行层序遍历,注意队列基本操作方式
  • 层序遍历即为图论中的广度优先搜索

思路

  • 通过size来记录每一层需要的长度,再遍历时需要保持固定
/**
 * 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 != nullptr) que.push(root);
        while (!que.empty()) {
            int size = que.size();
            vector<int> vec;
            while (size--) { // 这里一定要使用固定大小,不能用que.size(),
            // 此时每次循环结束size会变化,该处取的是本层的固定大小快照
                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;
    }
};

226. 翻转二叉树

心得

  • 一看就会,一写就废,需要动手画画加深理解
  • 需要想好本层逻辑具体做什么,每次遍历到位置需要做什么,剩下按照框架即可

题解

  • 递归迭代均可,考虑好何种遍历方式,本题采用前后序均可,层序遍历也可,
  • 唯独中序不行,如果必须中序需要在中序基础上修改,中序遍历后发生了翻转,需要再次遍历同侧位置,否则会被翻转2次,即左中左或者使用统一迭代法(使用栈而非指针来记录位置)可以不用修改实现
// 前序递归
class Solution {
public:
    TreeNode* invertTree(TreeNode* root) {
        if (root == nullptr) return root;
        swap(root->left, root->right);
        invertTree(root->right);
        invertTree(root->left);
        return root;
    }
};
// 前序迭代
class Solution {
public:
    TreeNode* invertTree(TreeNode* root) {
        stack<TreeNode*> st;
        if (root == nullptr) return root;
        st.push(root);
        while (!st.empty()) {
            TreeNode* node = st.top();
            st.pop();
            swap(node->left, node->right);
            if (node->right) st.push(node->right);
            if (node->left) st.push(node->left);
        }
        return root;
    }
};

101. 对称二叉树

心得

  • 开始想的是中序遍历然后遍历结果数组是否对称,部分情况无法处理
  • 想好处理逻辑,按照步骤写好递归
  • 对于迭代法,想好处理逻辑和结构即可

题解

  • 只能采用“后序遍历”,其实是变种后序,判断对称在于判断内外侧是相同,其实也就是左右中遍历和右左中遍历结果是否相同
  • 同样可以用非递归——队列来实现,此处非层序遍历而且队列完全可以由栈替换,只是用来保存对应位置结点用于取出时判断使用
// 递归
class Solution {
public:
    bool traversal(TreeNode* left, TreeNode* right) {
        // 处理空节点情况
        if (left == nullptr && right != nullptr) return false;
        else if (left != nullptr && right == nullptr) return false;
        else if (left == nullptr && right == nullptr) return true;
        else if (left->val != right->val) return false;
        // 此时左右结点非空,且值相等,才到递归处理逻辑
        bool isOutside = traversal(left->left, right->right); // 外侧是否对称
        bool isInside = traversal(left->right, right->left); // 内侧是否等
        bool isSame = isOutside && isInside;
        return isSame;
    }
    bool isSymmetric(TreeNode* root) {
        if (root == nullptr) return true;
        return traversal(root->left, root->right);
    }
};
// 迭代法
class Solution {
public:
    bool isSymmetric(TreeNode* root) {
        queue<TreeNode*> que;
        if (root != nullptr) {
            que.push(root->left);
            que.push(root->right);
        }
        while (!que.empty()) {
            TreeNode* left = que.front();
            que.pop();
            TreeNode* right = que.front();
            que.pop();
            if (left == nullptr && right == nullptr) continue;
            // 合并另外三种情况
            if (!left || !right || (left->val != right->val)) {
                return false;
            }
            que.push(left->left);
            que.push(right->right);
            que.push(left->right);
            que.push(right->left);
        }
        return true;
    }
};