代码随想录Day15

91 阅读3分钟

二叉树的统一迭代法

// 标记法:
// 将访问的节点放入栈中,把要处理的节点也放入栈中但是要做标记。
// 如何标记呢,就是要处理的节点放入栈之后,紧接着放入一个空指针作为标记。
class Solution {
public:
    // 中序遍历
    vector<int> inorderTraversal(TreeNode* root) {
        // 存储遍历结果的数组
        vector<int> result;
        // 辅助遍历的栈
        stack<TreeNode*> st;
        // 根结点不为空,则把根节点压入栈中
        if (root != NULL) {
            st.push(root);
        }
        while (!st.empty()) {
            TreeNode* node = st.top();
            if (node != NULL) {
                // 弹出该节点,避免重复操作,因为出栈是入栈的逆序,所以左根右——>右根左
                st.pop();
                // 右结点
                if (node->right) {
                    st.push(node->right);
                }
                // 根结点,访问过但是还没有处理,加入空节点做标记
                st.push(node);
                st.push(NULL);
                // 左结点
                if (node->left) {
                    st.push(node->left);
                } 
            } else {
                // 此分支为遇见栈中空结点,也就是访问过根节点之后的情况
                // 将空结点弹出栈
                st.pop();
                // 重新取出栈中元素
                node = st.top();
                st.pop();
                result.push_back(node->val);
            }
        }
        return result;
    }

    // 前序遍历
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> result;
        stack<TreeNode*> st;
        if (root != NULL) {
            st.push(root);
        }
        // 前序遍历:根左右——>右左根
        while (!st.empty()) {
            TreeNode* node = st.top();
            if (node != NULL) {
                st.pop();
                if (node->right != NULL) {
                    st.push(node->right);
                }
                if (node->left != NULL) {
                    st.push(node->left);
                }
                st.push(node);
                st.push(NULL);
            } else {
                // 遇见空结点
                st.pop();
                node = st.top();
                st.pop();
                result.push_back(node->val);
            }
        }
        return result;
    }

    // 后序遍历
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> result;
        stack<TreeNode*> st;
        if (root != NULL) {
            st.push(root);
        }
        // 左右根——>根右左
        while (!st.empty()) {
            TreeNode* node = st.top();
            if (node != NULL) {
                st.pop();
                st.push(node);
                st.push(NULL);
                if (node->right) {
                    st.push(node->right);
                }
                if (node->left) {
                    st.push(node->left);
                }
            } else {
                st.pop();
                node = st.top();
                st.pop();
                result.push_back(node->val);
            }
        }
        return result;
    }
 };

102.二叉树的层序遍历

力扣题目链接

文章讲解

102二叉树的层序遍历.gif

// 二叉树层序遍历模板
    vector<vector<int>> levelOrder(TreeNode* root) {
        queue<TreeNode*> que;
        vector<vector<int>> result;
        if (root != NULL) {
            que.push(root);
        }
        while (!que.empty()) {
            // 使用固定大小size,que的size会变化
            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;
    }   
    // 二叉树层序遍历递归版
    void order(TreeNode* cur, vector<vector<int>>& res, int depth) {
        if (cur == NULL) {
            return;
        }
        if (res.size() == depth) {
            res.push_back(vector<int>());
        }
        res[depth].push_back(cur->val);
        order(cur->left, res, depth + 1);
        order(cur->right, res, depth + 1);
    }
    vector<vector<int>> levelOrder1(TreeNode* root) {
        vector<vector<int>> result;
        int depth = 0;
        order(root, result, depth);
        return result;
    }

226.翻转二叉树

力扣题目链接

文章讲解

这道题目使用前序遍历和后序遍历都可以,唯独中序遍历不方便,因为中序遍历会把某些节点的左右孩子翻转了两次!

// 递归法
    TreeNode* invertTree1(TreeNode* root) {
        if (root == NULL) {
            return root;
        }
        swap(root->left, root->right);
        invertTree1(root->left);
        invertTree1(root->right);
        return root;
    }
    // 前序遍历
    TreeNode* invertTree2(TreeNode* root) {
        if (root == NULL) {
            return root;
        }
        stack<TreeNode*>st;
        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;
        }
    }
    // 前序遍历 统一迭代法
    TreeNode* invertTree3(TreeNode* root) {
        stack<TreeNode*> st;
        if (root != NULL) {
            st.push(root);
        }
        while (!st.empty()) {
            TreeNode* node = st.top();
            if (node != NULL) {
                st.pop();
                if (node->right) {
                    st.push(node->right);
                }
                if (node->left) {
                    st.push(node->left);
                }
                st.push(node);
                st.push(NULL);
            } else {
                // 遇见空指针
                st.pop();
                node = st.top();
                st.pop();
                swap(node->left, node->right);
            }
        }
        return root;
    }
    // 层序遍历法
    TreeNode* invertTree4(TreeNode* root) {
        queue<TreeNode*> que;
        if (root != NULL) {
            que.push(root);
        }
        while (!que.empty()) {
            int size = que.size();
            for (int i = 0; i < size; ++i) {
                TreeNode* node = que.front();
                que.pop();
                swap(node->left, node->right);
                if (node->left) {
                    que.push(node->left);
                }
                if (node->right) {
                    que.push(node->right);
                }
            }
            
        }
        return root;
    }

101. 对称二叉树

力扣题目链接

文章讲解

image.png

// 递归函数
    bool compare(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;
        }
        // 此时左右结点不为空且数值相同
        bool outside = compare(left->left, right->right);
        bool inside = compare(left->right, right->left);
        bool isSame = outside && inside;
        return isSame;
    }

    // 递归法
    bool isSymmetric(TreeNode* root) {
        if (root == NULL) {
            return true;
        }
        return compare(root->left, root->right);
    }

    bool isSymmetric1(TreeNode* root) {
        if (root == NULL) return true;
        stack<TreeNode*> st; // 这里改成了栈
        st.push(root->left);
        st.push(root->right);
        while (!st.empty()) {
            TreeNode* leftNode = st.top(); st.pop();
            TreeNode* rightNode = st.top(); st.pop();
            if (!leftNode && !rightNode) {
                continue;
            }
            if ((!leftNode || !rightNode || (leftNode->val != rightNode->val))) {
                return false;
            }
            st.push(leftNode->left);
            st.push(rightNode->right);
            st.push(leftNode->right);
            st.push(rightNode->left);
        }
        return true;
    }