leetcode刷题笔记_树

本文介绍了如何使用递归实现二叉树的前序、中序、后序遍历,并展示了如何通过这些遍历方式构建和还原二叉树,包括层序遍历的应用。同时涵盖了二叉树深度计算、对称性判断、路径和计算及序列化反序列化技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

树的遍历

前序遍历

/**
 * 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 preorder(TreeNode* root,vector<int> &res)
    {
        if(root==nullptr)
            return;
        res.push_back(root->val);
        preorder(root->left,res);
        preorder(root->right,res);
    }
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> res;
        preorder(root,res);
        return res;
    }
};

中序遍历

/**
 * 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 inorder(TreeNode* root,vector<int>& res)
    {
        if(root==nullptr)
            return;
        inorder(root->left,res);
        res.push_back(root->val);
        inorder(root->right,res);
    }
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> res;
        inorder(root,res);
        return res;
    }
};

后序遍历

/**
 * 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 postOrder(TreeNode* root,vector<int>& res)
    {
        if(root==nullptr)
            return;
        postOrder(root->left,res);
        postOrder(root->right,res);
        res.push_back(root->val);

    }
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> arr;
        postOrder(root,arr);
        return arr;

    }
};

层序遍历

/**
 * 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>> res;
        if(root==nullptr)
            return res;
        
        queue<TreeNode*> qu;
        qu.push(root);
        int level=0;
        while(!qu.empty())
        {
            level++;
            vector<int> levevRes; 
            //每一层的个数等于当前的队列长度
            
            int levelSize=qu.size();           
            for(int i=0;i<levelSize;i++)
            {
                TreeNode* cur=qu.front();
                levevRes.push_back(qu.front()->val);
                qu.pop();
                if(cur->left)
                {
                    qu.push(cur->left);
                    
                }
                if(cur->right)
                {
                    qu.push(cur->right);
                   
                }
            }
          res.push_back(levevRes);  
        }
        return level;



    }
};

运用递归解决问题

二叉树树的深度

/**
 * 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) {
         vector<vector<int>> res;
        if(root==nullptr)
            return 0;
        
        queue<TreeNode*> qu;
        qu.push(root);
        int level=0;
        while(!qu.empty())
        {
            level++;
            vector<int> levevRes; 
            //每一层的个数等于当前的队列长度
            
            int levelSize=qu.size();           
            for(int i=0;i<levelSize;i++)
            {
                TreeNode* cur=qu.front();
                levevRes.push_back(qu.front()->val);
                qu.pop();
                if(cur->left)
                {
                    qu.push(cur->left);
                    
                }
                if(cur->right)
                {
                    qu.push(cur->right);
                   
                }
            }
          res.push_back(levevRes);  
        }
        return level;
    }
};

对称二叉树

给定一个二叉树,检查它是否是镜像对称的。

/**
 * 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) {
        return check(root,root);
    }
    bool check(TreeNode*left,TreeNode*right)
    {
        if(left==nullptr&&right==nullptr)
        {
            return true;
        }
        if(left==nullptr||right==nullptr)
        {
            return false;
        }
        return (left->val==right->val)&&check(left->left,right->right)&&check(left->right,right->left);
    }
};

路径总和

/**
 * 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 hasPathSum(TreeNode* root, int targetSum) {
        //如果根节点为空返回false
        if(root==nullptr)
            return false;
        //如果左右都为空此时的总和就是到叶子结点的路径和
        if(root->left==nullptr&&root->right==nullptr)
            return root->val==targetSum;
        return hasPathSum(root->left,targetSum-root->val)||hasPathSum(root->right,targetSum-root->val);

    }
};

总结

从前序遍历与后序遍历构造二叉树

/**
 * 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* buildTree(vector<int>& inorder, vector<int>& postorder) {
        if(inorder.size()==0)
            return nullptr;
        
        return dfs(inorder,postorder,0,inorder.size()-1,0,postorder.size()-1);
        

    }
    
    //中序遍历的根节点在中间
    TreeNode* dfs(vector<int>& inorder, vector<int>& postorder,int inStart,int inEnd,int postStart,int postEnd){
        if(inStart>inEnd)
            return nullptr;
        //树的根节点的后序遍历的最后一个结点
        TreeNode* root=new TreeNode(postorder[postEnd]);
        //TreeNode* root=new TreeNode(20);
            //如果中序遍历的头和尾都相等,则说明已经访问完,返回这棵树
        if(inStart==inEnd)
            return root;
        
        
        //以根节点的值为中心,左右两边分别是根节点的子树的结点
        int mid=0;
        //从当前中序遍历的数组的第一个点开始搜索,直到找到根节点
        while((root->val)!=inorder[inStart+mid])mid++;
        //左子树是根节点中序遍历左边那部分
        root->left= dfs(inorder,postorder,inStart,inStart+mid-1,postStart,postStart+mid-1);
        //右子树是根节点中序遍历右边那部分
        root->right=dfs(inorder,postorder,inStart+mid+1,inEnd,postStart+mid,postEnd-1);
        return root;
        
    }
};

从前序遍历与中序遍历构造二叉树

/**
 * 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* buildTree(vector<int>& preorder, vector<int>& inorder) {
        //如果前序遍历或者中序遍历长度为0或者长度不相等,树不存在
        int prelen=preorder.size();
        int inlen=inorder.size();
        if(prelen==0||inlen==0||prelen!=inlen)
            return nullptr;
        return dfs(preorder,inorder,0,prelen-1,0,inlen-1);
        
        


    }
    TreeNode* dfs(vector<int>& preorder, vector<int>& inorder,int preStart,int preEnd,int inStart,int inEnd)
    {
        //如果坐标越界返回空值
        if(preStart>preEnd)
            return nullptr;
        //根节点是先序遍历的第一个结点
        TreeNode* root=new TreeNode(preorder[preStart]) ;
        //如果两者相等,说明遍历完了这棵树,返回根节点
        if(preStart==preEnd)
            return root;
        //找到中序遍历中和根节点相同的结点的相对坐标,mid-1其实就是左子树的结点个数
        int mid=0;
        while(root->val!=inorder[inStart+mid])mid++;
        //中序遍历中根节点两边分别为左右子树
        root->left=dfs(preorder,inorder,preStart+1,preStart+mid,inStart,inStart+mid-1);
        root->right=dfs(preorder,inorder,preStart+mid+1,preEnd,inStart+mid+1,inStart);
        return root;
    }
};

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

/*
// 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) {
        //如果根节点为空返回root
        if(root==nullptr)
            return nullptr;
        //把根节点的左右结点连接
        dfs(root->left,root->right);
        return root;

        
    }
    void dfs(Node* left,Node* right)
    {
        //如果左右结点有空值,返回nullptr
        if(left==nullptr||right==nullptr)
            return;
        //把左右结点连起来
        
        left->next=right;
        dfs(left->left,left->right);
        dfs(left->right,right->left);
        dfs(right->left,right->right);
    }
};

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

/*
// 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) {
        if(root==nullptr)
            return nullptr;
        if(root->left!=nullptr)
        {
            //如果左右孩子不为空,左孩子指向右孩子
            if(root->right!=nullptr)
            {
                root->left->next=root->right;
            }
            //左孩子不为空,右孩子为空,左孩子指向父节点的next结点的最左边那个孩子
            else{
                root->left->next=getFirstChild(root->next);
            }
        }
        //右孩子不为空那就让右孩子连接
        if(root->right!=nullptr)
        {
            root->right->next=getFirstChild(root->next);
        }
        //再连接左子树和右子树
        //要先连接右子树,才能确保找到next结点
        connect(root->right);
        connect(root->left);
        return root;
        
    }
    //用于获取当前结点的最左边的孩子结点
    Node* getFirstChild(Node* root){
        if(root==nullptr)
            return nullptr;
        //左孩子不为空,返回左孩子
        if(root->left!=nullptr)
            return root->left;
        //左孩子不为空,右孩子为空,返回右孩子
        if(root->right!=nullptr)
            return root->right;
        //否则再搜索下一个结点
        return getFirstChild(root->next);
        
    }
};

二叉树的最近公共祖先

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        //如果root是空或者两个节点有一个结点为根节点,那就直接返回根节点
        //因为此时根节点就是最近公共祖先
        if(root==nullptr||root==p||root==q)
            return root;
        //否则就找左右子树里pq的最近公共祖先
        TreeNode*left=lowestCommonAncestor(root->left,p,q);
        TreeNode*right=lowestCommonAncestor(root->right,p,q);
        //如果左孩子找不到pq的话说明在右孩子上
        if(left==nullptr)
            return right;
        //如果右孩子找不到pq那就说明在左孩子上
        if(right==nullptr)
            return left;
        //如果左右孩子都找到了说明一个在左孩子一个在右孩子上。返回当前结点即可
        return root;
        

        
    }
};

二叉树的序列化和反序列化

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
 TreeNode* node;
class Codec {
public:

    // Encodes a tree to a single string.
    string serialize(TreeNode* root) {
        node=root;
        return "";
        
    }

    // Decodes your encoded data to tree.
    TreeNode* deserialize(string data) {
        return node;
    }
};

// Your Codec object will be instantiated and called as such:
// Codec ser, deser;
// TreeNode* ans = deser.deserialize(ser.serialize(root));
  • 写了一个晚上没写出来,看到题解我惊呆了
  • 我思路是把原来结点转化为前序遍历和中序遍历,然后根据中序遍历和前序遍历来转化成原来的数,但是一直有问题,明天再看看问题在哪
  • 还看到用层序遍历存树然后再还原的,这个也好牛呀
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值