(15/60)层序遍历、翻转二叉树、对称二叉树

层序遍历

leetcode:

102.二叉树的层序遍历

思路

  1. root如果非空就入队

  2. 队列不空时,循环:

    • 开头记录当前队列size

    • 循环size次:

      • 取队首结点,队首出队;
      • 本层元素数组vec记录node->val
      • (判断非空)左、右孩子入队

复杂度分析

时间复杂度:O(N)。

空间复杂度:O(N)。

注意点

代码实现

/**
 * 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 != NULL) que.push(root);

        while(!que.empty()){
            int size = que.size();
            vector<int> vec;
            while(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;
    }
};

429. N叉树的层序遍历

思路

层序遍历基础上,左、右结点入队改为遍历children数组的元素入队。

复杂度分析

时间复杂度:O(N)。

空间复杂度:O(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;
        queue<Node*> que;
        if(root != NULL) que.push(root);
        while(!que.empty()){
            int size = que.size();
            vector<int> vec;
            while(size--){
                Node* node = que.front(); que.pop();
                vec.push_back(node->val);
                for(Node* node : node->children){
                    if(node != NULL) que.push(node);
                }
            }
            result.push_back(vec);
        }

        return result;
    }
};

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

思路

层序遍历基础上,若非该层最后一个结点:取队首结点nextNode,next->next = nextNode;否则next->next = NULL

复杂度分析

时间复杂度:O(N)。

空间复杂度:O(N)。

注意点

代码实现

/*
// 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) {
        queue<Node*> que;
        if(root != NULL) que.push(root);
        while(!que.empty()){
            int size = que.size();
            for(int i = 0;i < size;i++){
                Node* node = que.front(); que.pop();
                if(i == size - 1) node->next = NULL;
                else{
                    Node* nextNode = que.front();
                    node->next = nextNode;
                }
                if(node->left) que.push(node->left);
                if(node->right) que.push(node->right);
            }
        }

        return root;
    }
};

111. 二叉树的最小深度

思路

左右子结点都为NULL的就是叶子结点。又因为是层序遍历,第一个碰到的叶子结点就是最浅的叶子结点。

复杂度分析

时间复杂度:O(N)。

空间复杂度:O(N)。

注意点

代码实现

/**
 * 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 minD = INT32_MAX;
        int count = 0;
        queue<TreeNode*> que;
        if(root != NULL) que.push(root);
        while(!que.empty()){
            int size = que.size();
            count++;
            while(size--){
                TreeNode* node = que.front(); que.pop();
                if(node->left) que.push(node->left);
                if(node->right) que.push(node->right);
                // 左、右结点都为空时就是叶子结点
                // 因为是层序遍历,在第一次遇见叶子时就是最小深度
                if(!node->left && !node->right) return count; 
            }
        }

        return 0;
    }
};

翻转二叉树

leetcode:226. 翻转二叉树

前序、后序遍历

思路

同递归遍历,把数组记录那步改为交换。

复杂度分析

时间复杂度:O(N)。

空间复杂度:O(N)。

注意点

代码实现

/**
 * 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:
    void reverseTree(TreeNode* root){
        if(root == NULL) return;
        swap(root->left,root->right);	// 根
        reverseTree(root->left);	// 左
        reverseTree(root->right);	// 右
    }
    TreeNode* invertTree(TreeNode* root) {
        reverseTree(root);
        return root;
    }
};

中序遍历

思路

中序翻转后原来的左右互换了,因此要左、根、左。

复杂度分析

时间复杂度:O(N)。

空间复杂度:O(N)。

注意点

代码实现

/**
 * 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:
    void reverseTree(TreeNode* root){
        if(root == NULL) return;
        reverseTree(root->left);	// 左
        swap(root->left,root->right);	// 根
        reverseTree(root->left);	// 左
    }
    TreeNode* invertTree(TreeNode* root) {
        reverseTree(root);
        return root;
    }
};

对称二叉树

leetcode:101. 对称二叉树

递归法

思路

递归三部曲

  1. 返回值bool,传入参数:左结点、右结点。
  2. 退出条件:
    • 左右都空-true
    • 左空-false
    • 右空-false
    • 左右值不相等-false
  3. 单层递归逻辑:
    • 处理外层
    • 处理内层
    • 处理根结点

复杂度分析

时间复杂度:O(N)。遍历一遍。

空间复杂度:O(N)。

注意点

  1. 前、中、后序主要取决于处理中间结点的时机,不一定是先左后右。此处就是先处理外层,再处理内层。
  2. 条件判断的顺序:(利用短路效应,尽可能简化条件的写法)
    1. 左右都空
    2. 左空
    3. 右空
    4. 左右值不相等

代码实现

/**
 * 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 compare(TreeNode* left,TreeNode* right){
        if(!left && !right) return true;	
        else if( !left || !right || (left->val != right->val )) return false;
        bool outside = compare(left->left,right->right);
        bool inside = compare(left->right,right->left);
        
        return outside && inside;
    }

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

栈或队列迭代法

思路

  1. 结点入栈(先外侧、再内侧)
  2. 对比左右结点指针

复杂度分析

时间复杂度:O(N)。

空间复杂度:O(N)。

注意点

  1. 前面已经判空了,后面可以直接添加结点。

代码实现

/**
 * 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) {
        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;
    }
};
posted @ 2024-02-07 21:15  Tazdingo  阅读(1800)  评论(0)    收藏  举报