代码随想录算法训练营|二叉树内容复习

双指针内容复习

二叉树递归遍历

类似于图论的深搜

首先是二叉树的递归三部曲

  • 确定递归函数的参数和初始条件

  • 确定递归的终止条件

  • 确定单层递归的逻辑

144前序遍历,145后序,94中序,虽然很简单,但是时间长了不写,三个没有一个遍通过的

二叉树层序遍历

再看发现确实还是有很多细节,层序遍历的核心是用队列实现的。队列的类型是TreeNode* 用来存放指针的,但是定义的数组类型是int型的,用来存放二叉树的结点的val

107. 二叉树的层序遍历 II,在层序的基础上加一个reverse库函数对数组进行翻转即可

  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:
    vector<int> rightSideView(TreeNode* root) {
        queue<TreeNode*> que;
        if (root != NULL) que.push(root);
        vector<int> result;
        while (!que.empty()) {
            int size = que.size();
            while (size--) {
                TreeNode* cur = que.front();
                // cout << size << endl;
                que.pop();
                if (size == 0) {
                    result.push_back(cur->val);
                }
                if (cur->left != NULL) que.push(cur->left);
                if (cur->right != NULL) que.push(cur->right);
            }
        }
        return result;
    }
};

637. 二叉树的层平均值 也比较简单,每一层的值相加起来之后除以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<double> averageOfLevels(TreeNode* root) {
        queue<TreeNode*> que;
        vector<double> vec;
        que.push(root);
        while (!que.empty()) {
            int size = que.size();
            double len = size;
            long sum = 0;
            while (size--) {
                TreeNode* cur = que.front();
                que.pop();
                sum += cur->val;
                if (cur->left != NULL) que.push(cur->left);
                if (cur->right != NULL) que.push(cur->right);
            }
            vec.push_back(sum / len);
        }
        return vec;

    }
};

429. N 叉树的层序遍历 这个是第一次处理N叉树,和二叉树的定义不一样,不过核心的思路没有变,今天写了两个版本的代码。

这个是层序遍历的标准代码,简单易懂,注意就是在每次pop完之后,要及时将pop出来的元素加入到vec中。这里表示的是处理当前结点

点击查看代码
/*
// 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) {
        queue<Node*> que;
        vector<vector<int>> result;
        if(root != NULL) que.push(root);
        while (!que.empty()) {
            int size = que.size();
            vector<int> vec;
            while (size--) {
                Node* cur = que.front();
                que.pop();
                vec.push_back(cur->val);
                for (int i = 0; i < cur->children.size(); i++) {
                    if (cur->children.size() > 0) {
                        que.push(cur->children[i]);
                    }
                }
            }
            result.push_back(vec);
        }
        return result;
    
    }
};

写的第二个版本是这样的,刚开始写这个版本的时候有点稀里糊涂的,不过后来一想,这个其实处理的是当前结点的孩子结点,这样就有点麻烦了

点击查看代码
/*
// 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) {
        queue<Node*> que;
        vector<vector<int>> result;
        if(root != NULL) {
            que.push(root);
            vector<int> vec;
            vec.push_back(root->val);
            result.push_back(vec);
        }
        else return result;
        
        while (!que.empty()) {
            int size = que.size();
            vector<int> vec;
            while (size--) {
                Node* cur = que.front();
                que.pop();
                for (int i = 0; i < cur->children.size(); i++) {
                    if (cur->children.size() > 0) {
                        que.push(cur->children[i]);
                        vec.push_back(cur->children[i]->val);
                    }
                }
            }
            result.push_back(vec);
        }
        result.pop_back();
        return result;
    
    }
};

这两种不同的处理方式让我想到了,之前的105有向图的完全可达性中,对深搜处理的不同讨论,分别是当前结点还有当前结点的下一个结点的两种不同的方式。

515. 在每个树行中找最大值 感觉和上面你的求层平均值差不多

处理当前结点

点击查看代码
/**
 * 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<int> largestValues(TreeNode* root) {
        queue<TreeNode*> que;
        vector<int> result;
        if (root != NULL) que.push(root);
        while (!que.empty()) {
            int size = que.size();
            int m = INT_MIN;
            while (size--) {
                TreeNode* cur = que.front();
                que.pop();
                m = max(m, cur->val);
                if (cur->left != NULL) que.push(cur->left);
                if (cur->right != NULL) que.push(cur->right);
            }
            result.push_back(m);
            
        }
        return result;
    }
};

处理下一个结点

点击查看代码
/**
 * 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<int> largestValues(TreeNode* root) {
        queue<TreeNode*> que;
        vector<int> result;
        if (root != NULL) que.push(root);
        else return result;
        int m = max(INT_MIN, root->val);
        while (!que.empty()) {
            int size = que.size();
            result.push_back(m);
            m = INT_MIN;
            while (size--) {
                TreeNode* cur = que.front();
                que.pop();
                if (cur->left != NULL) {
                    que.push(cur->left);
                    m = max(m, cur->left->val);
                }
                if (cur->right != NULL) {
                    que.push(cur->right);
                    m = max(m, cur->right->val);
                } 
            }
            
        }
        return result;
    }
};

翻转二叉树

226.翻转二叉树 核心就是要看自己使用的具体是哪种遍历方式,注意中序的翻转顺序比较特殊,导致其应该对左子树进行两次翻转。

中序遍历

点击查看代码
/**
 * 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:
    TreeNode* invertTree(TreeNode* root) {
        if (root == NULL) return NULL;
        invertTree(root->left);
        swap(root->left, root->right);
        invertTree(root->left);
        return root;
    }
};

对称二叉树

101. 对称二叉树 这个就是需要同时进行两个子树的比较,还是比较固定的写法,需要用到后序遍历,注意他比较的是左右子树的共同外侧和共同内侧。

二叉树的最大深度

104.二叉树的最大深度 二叉树的深度一般由前序遍历来求,高度一般由后序遍历来求,本题可以用后序来做。其实质也是先算了二叉树的高度,之后高度==深度,所以才求出来深度。

点击查看代码
/**
 * 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 maxDepth(TreeNode* root) {
        if (root == NULL) return 0;
        int lheight = maxDepth(root->left);
        int rheight = maxDepth(root->right);
        int result = max(lheight, rheight) + 1;
        return result;
        
    }
};

二叉树的最小深度

111. 二叉树的最小深度 二叉树的最小深度同样使用的是后序遍历,计算最小高度,之后再将最小高度转换为最小深度(这一步就是直接等于的关系)。在递归最小高度时,要注意如果出现一棵子树为空,那么此时需要从不空的子树高度上+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:
    int minDepth(TreeNode* root) {
        if (root == NULL) return 0;
        int lheight = minDepth(root->left);
        int rheight = minDepth(root->right);
        int result;
        if (root->left != NULL && root->right == NULL) result = 1 + lheight;
        if (root->left == NULL && root->right != NULL) result = 1 + rheight;
        if (root->left != NULL && root->right != NULL) result = 1 + min(lheight, rheight);
        return result;
    }
};

完全二叉树的结点个数

222.完全二叉树的节点个数 首先是用后序遍历,5行代码很简单就过了。

这是普通的二叉树的解法

点击查看代码
/**
 * 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 countNodes(TreeNode* root) {
        if (root == NULL) return 0;
        int lnum = countNodes(root->left);
        int rnum = countNodes(root->right);
        int result = lnum + rnum + 1;
        return result;
    }
};

其实这里用完全二叉树的性质还是有点不太好理解的,他有两个终止条件注意

点击查看代码
/**
 * 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 countNodes(TreeNode* root) {
        //确定递归的终止条件
        if (root == NULL) return 0;
        TreeNode* left = root->left;
        TreeNode* right = root->right;
        int lleft = 0;
        int lright = 0;
        while (left != NULL) {
            lleft++;
            left = left->left;
        }
        while (right != NULL) {
            lright++;
            right = right->right;
        }
        if (lleft == lright) return (2 << lleft) - 1;

        // 确定单层递归的逻辑
        int lresult = countNodes(root->left);
        int rresult = countNodes(root->right);
        return lresult + rresult + 1;
    }
};

平衡二叉树

110. 平衡二叉树 再写平衡二叉树的时候,感觉还是有一些地方不太好写,这次从后序遍历开始手搓,但是相比之前的代码,不自觉写了很多

有一个测试用例,不太好搞[1,2,2,3,null,null,3,4,null,null,4],这个画出来是一个根结点是平衡的,但是其他结点就不是平衡的了。一开始还纳闷呢,所以这里就需要有一步操作,就是在递归的时候,一旦发现有某个结点的高度差大于1了,那么就及时进行标注-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 {
private:
    int getHeight(TreeNode* root) {
        if (root == NULL) return 0;
        int lheight = getHeight(root->left);
        if (lheight == -1) return -1;
        int rheight = getHeight(root->right);
        if (rheight == -1) return -1;
        int result;
        if (lheight >= rheight) {
            result = lheight - rheight;
        } else {
            result = rheight - lheight;
        }
        return result > 1 ? -1 : max(lheight, rheight) + 1;
    }
public:
    bool isBalanced(TreeNode* root) {
        if (root == NULL) return true; 
        int lheight = getHeight(root->left);
        int rheight = getHeight(root->right);
        if (lheight == -1 || rheight == -1) {
            return false;
        }
        cout << lheight << ' ' << rheight << endl;
        cout << abs(lheight - rheight) << endl;
        if (abs(lheight - rheight) <= 1) {
            return true;
        }
        return false;
    }
};

二叉树的所有路径

257. 二叉树的所有路径 这个题再写的时候,又不会了,用到了回溯算法。首先是三部曲,确定递归的终止条件这里有点特殊不一样。还有就是再单层递归的逻辑,在每一部分要加上回溯的部分。

点击查看代码
/**
 * 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 {
private:
    void traversal(TreeNode* root, vector<string>& result, vector<int> &path) {
        // 前序的根结点在这里
        path.push_back(root->val);
        if (root != NULL && root->left == NULL && root->right == NULL) {
            string spath;
            for (int i = 0; i < path.size() - 1; i++) {
                spath += to_string(path[i]); 
                spath += "->";
            }
            spath += to_string(path[path.size() - 1]);
            result.push_back(spath);
            return;
        }
        
        if (root->left) {
            traversal(root->left, result, path);
            path.pop_back();
        }
        if (root->right) {
            traversal(root->right, result, path);
            path.pop_back();
        }
        
    }
public:
    vector<string> binaryTreePaths(TreeNode* root) {
        vector<string> result;
        vector<int> path;
        if (root == NULL) return result;
        traversal(root, result, path);
        return result;
    }
};

左叶子之和

404. 左叶子之和 本题的递归方式是最特殊的,用int进行递归,另外要注意其只是对左子树进行计数。

点击查看代码
/**
 * 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 sumOfLeftLeaves(TreeNode* root) {
        if (root == NULL) return 0;
        // 单层递归的逻辑,是先递归左,后递归右
        int lsum = sumOfLeftLeaves(root->left);
        if (root->left != NULL && root->left->left == NULL && root->left->right == NULL) {
            lsum = root->left->val;
        }

        int rsum = sumOfLeftLeaves(root->right);

        int result = lsum + rsum;
        return result;
    }
};

找树左下角的值

513.找树左下角的值 这个题找最底层,左边第一个即可。因为是递归遍历,是向深处遍历的,所以要不断进行回溯,看路径中是否有大于当前最大深度的结点出现。

点击查看代码
/**
 * 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 {
private:
    int result;
    int maxDepth = INT_MIN;

    void traversal(TreeNode* root, int depth) {
        if (root != NULL && root->left == 0 && root->right == 0) {
            if (depth > maxDepth) {
                maxDepth = depth;
                result = root->val;
                return;
            }
        }

        if (root->left) {
            depth++;
            traversal(root->left, depth);
            depth--;
        }

        if (root->right) {
            depth++;
            traversal(root->right, depth);
            depth--;
        }
    }
public:
    int findBottomLeftValue(TreeNode* root) {
        traversal(root, 1);
        return result;
    }
};
posted on 2025-04-05 11:11  bnbncch  阅读(15)  评论(0)    收藏  举报