第六章 二叉树part02

2026.02.10 第十四天

C++自带了swap函数,可以直接交换两个子节点的地址

226 翻转二叉树

注意每次翻转只更换了当前节点的父节点,也就是调整了当前节点的顺序,而没有翻转当前节点的子节点,因此只需要递归遍历一遍所有节点即可。

可以使用前序、后序和中序遍历,期终中序两次翻转都要使用left。

递归法:

class Solution {
public:
    TreeNode* invertTree(TreeNode* root) {
        if(root != nullptr) {
            invertTree(root->left);
            swap(root->left, root->right);
            //invertTree(root->right);
            invertTree(root->left);
        }
        else {
            return nullptr;
        }
        return root;
    }
};

迭代法实现:在二叉树part01的基础上进行相应修改即可。

迭代法:
前序遍历:

class Solution {
public:
    TreeNode* invertTree(TreeNode* root) {
        if(root == nullptr) return root;
        stack<TreeNode*> st;
        st.push(root);
        while(!st.empty()) {
            TreeNode* temp = st.top();
            st.pop();
            swap(temp->left, temp->right);
            if(temp->left) st.push(temp->left);
            if(temp->right) st.push(temp->right);
        }
        return root;
    }
};

前序遍历(统一迭代法):

class Solution {
public:
    TreeNode* invertTree(TreeNode* root) {
        stack<TreeNode*> st;
        if(root != nullptr) st.push(root);
        while(!st.empty()) {
            if(st.top() != nullptr) {
                TreeNode* temp = st.top();
                st.pop();
                if(temp->right) st.push(temp->right);
                if(temp->left) st.push(temp->left);
                st.push(temp);
                st.push(nullptr);
            }
            else {
                st.pop();
                TreeNode* temp = st.top();
                st.pop();
                swap(temp->left, temp->right);
            }
        }
        return root;
    }
};

广度优先遍历:

class Solution {
public:
    TreeNode* invertTree(TreeNode* root) {
        queue<TreeNode*> que;
        if(root != nullptr) 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 对称二叉树

比较的是两个子树的里侧和外侧的元素是否相等

本题遍历只能是“后序遍历”,因为我们要通过递归函数的返回值来判断两个子树的内侧节点和外侧节点是否相等。

正是因为要遍历两棵树而且要比较内侧和外侧节点,所以准确的来说是一个树的遍历顺序是左右中,一个树的遍历顺序是右左中。

递归法:

class Solution {
private:
    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 != nullptr && right != nullptr && left->val != right->val) {
            return false;
        }
        else {
            return compare(left->left, right->right) && compare(left->right, right->left);
        }
    }

public:
    bool isSymmetric(TreeNode* root) {
        if(root == nullptr) {
            return true;
        }
        else {
            return compare(root->left, root->right);
        }
    }
};

迭代法:

思路与递归法相同,借用栈或队列实现逻辑。

class Solution {
public:
    bool isSymmetric(TreeNode* root) {
        if(root == nullptr) {
            return true;
        }
        queue<TreeNode*> que;
        que.push(root->left);
        que.push(root->right);
        while(!que.empty()) {
            TreeNode* leftNode = que.front();
            que.pop();
            TreeNode* rightNode = que.front();
            que.pop();
            if(!leftNode && !rightNode) {
                continue;
            }
            else if(!leftNode || !rightNode || (leftNode->val != rightNode->val)) {
                return false;
            }
            else {
                que.push(leftNode->left);
                que.push(rightNode->right);
                que.push(leftNode->right);
                que.push(rightNode->left);
            }
        }
        return true;
    }
};
class Solution {
public:
    bool isSymmetric(TreeNode* root) {
        if(root == nullptr) {
            return true;
        }
        stack<TreeNode*> sta;
        sta.push(root->left);
        sta.push(root->right);
        while(!sta.empty()) {
            TreeNode* leftNode = sta.top();
            sta.pop();
            TreeNode* rightNode = sta.top();
            sta.pop();
            if(!leftNode && !rightNode) {
                continue;
            }
            else if(!leftNode || !rightNode || (leftNode->val != rightNode->val)) {
                return false;
            }
            else {
                sta.push(leftNode->left);
                sta.push(rightNode->right);
                sta.push(leftNode->right);
                sta.push(rightNode->left);
            }
        }
        return true;
    }
};

104 二叉树的最大深度

本题可以使用前序(中左右),也可以使用后序遍历(左右中),使用前序求的就是深度,使用后序求的是高度。

二叉树节点的深度:指从根节点到该节点的最长简单路径边的条数或者节点数(取决于深度从0开始还是从1开始)
二叉树节点的高度:指从该节点到叶子节点的最长简单路径边的条数或者节点数(取决于高度从0开始还是从1开始)
而根节点的高度就是二叉树的最大深度,所以本题中我们通过后序求的根节点高度来求的二叉树最大深度。

class Solution {
private:
    int getDepth(TreeNode* node) {
        if(!node) {
            return 0;
        }
        else {
            int leftDepth = getDepth(node->left) + 1;
            int rightDepth = getDepth(node->right) + 1;
            return leftDepth >= rightDepth ? leftDepth : rightDepth;
        }
    }

public:
    int maxDepth(TreeNode* root) {
        return getDepth(root);
    }
};

144 二叉树的最小深度

这题的关键是怎样找到最小深度的叶子节点。

最小深度是从根节点到最近叶子节点的最短路径上的节点数量。注意是叶子节点。
什么是叶子节点,左右孩子都为空的节点才是叶子节点!

如果左子树为空,右子树不为空,说明最小深度是 1 + 右子树的深度。
反之,右子树为空,左子树不为空,最小深度是 1 + 左子树的深度。 最后如果左右子树都不为空,返回左右子树深度最小值 + 1 。

class Solution {
public:
    int getDpeth(TreeNode* node) {
        if(node == nullptr) return 0;
         int leftDepth = getDpeth(node->left);
         int rightDepth = getDpeth(node->right);
         if(!node->left && node->right) return 1 + rightDepth;
         if(node->left && !node->right) return 1 + leftDepth;
         return 1 + min(leftDepth, rightDepth);
    }

    int minDepth(TreeNode* root) {
        return getDpeth(root);
    }
};

上面的代码是左右中,也就是后序逻辑,由下往上计算,本质上是求高度。

层序遍历也可以实现,当遍历到左右节点都为空的节点时返回当前深度即可。

posted @ 2026-03-08 21:01  遠くの君  阅读(2)  评论(0)    收藏  举报