《剑指Offer》模块2 二叉树【15道二叉树帮助你掌握二叉树】

news2024/12/25 9:36:04

二叉树

  • 二叉树
    • 1. 树中两个结点的最低公共祖先
        • 方法一:公共路径
        • 方法二:递归
    • 2. 重建二叉树
        • 根据前序遍历和中序遍历 得到树
      • 补充题:树的遍历
    • 3. 二叉树的下一个节点
    • 4. 树的子结构( 递归中调用递归 )
    • 5. 二叉树的镜像(两个指针互换可用 swap)
    • 6. 对称的二叉树
        • 错解:通过根节点比较子节点
        • 正解:比较当前节点的值即可
    • 7. 不分行从上往下打印二叉树( 层序遍历二叉树bfs )
    • 8. 分行从上往下打印二叉树
        • ( 利用两个队列遍历 )
        • 利用数组个数 进行遍历
    • 9. 之字形打印二叉树
    • 10. 二叉搜索树的后序遍历序列
        • 考点:根据二叉搜索树的后序遍历的特点
    • 11. 二叉树中和为某一值的路径( dfs回溯 )
        • 注意:只能是根节点到叶子节点
    • 12. 序列化二叉树【序列化二叉树(本质就是 前中后序遍历)】
    • 13. 二叉搜索树的第k个结点
    • 14. 二叉树的深度【二叉树递归】
    • 15. 平衡二叉树【二叉树递归】

二叉树

1. 树中两个结点的最低公共祖先

原题链接

在这里插入图片描述

方法一:公共路径

分别找出根节点到两个节点的路径,则最后一个公共节点就是最低公共祖先了。

时间复杂度分析:需要在树中查找节点,复杂度为O(n)

/**
 * 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:
    int findPath(TreeNode*root, TreeNode* p, vector<TreeNode*>&path){
        if(!root)
            return 0;
        if(root->val==p->val){
            path.push_back(root);
            return 1;
        }
        int l = findPath(root->left,p,path);
        int r = findPath(root->right,p,path);
        if(l==1||r==1)
            path.push_back(root);
        return l==1||r==1;
    }
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        vector<TreeNode*>path1,path2;
        findPath(root,p,path1);
        findPath(root,q,path2);
        if(path1.empty()||path2.empty())
            return NULL;
        TreeNode* res =NULL;
        for(int i = 0;i<path1.size();i++){
            if(i>=path1.size()||i>=path2.size())
                break;
            if(path1[path1.size()-1-i]==path2[path2.size()-1-i])
                res = path1[path1.size()-1-i];
            else
                break;
        }
        return res;
    }
};

方法二:递归

考虑在左子树和右子树中查找这两个节点,如果两个节点分别位于左子树和右子树,则最低公共祖先为自己(root),若左子树中两个节点都找不到,说明最低公共祖先一定在右子树中,反之亦然。考虑到二叉树的递归特性,因此可以通过递归来求得。

时间复杂度分析:需要遍历树,复杂度为 O(n)

class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if(!root)
            return NULL;
        if(root==p||root==q)
            return root;
        TreeNode* left = lowestCommonAncestor(root->left, p, q);
        TreeNode* right = lowestCommonAncestor(root->right, p, q);
        if(left&&right)
            return root;
        if(left==NULL)
            return right;
        else
            return left;
    }
};
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    
    public boolean flag = false;
    public TreeNode ans = null;
    
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        dfs(root,p,q);
        return ans;
    }
    
    public TreeNode dfs(TreeNode root,TreeNode p,TreeNode q){
        
        if(root == null){
            return null;
        }
        
        TreeNode l = dfs(root.left,p,q);
        TreeNode r = dfs(root.right,p,q);
        
        if(l != null && r != null){
            ans = root;
            return ans;
        } else if((l != null || r != null) && (root.val == p.val || root.val == q.val)){
            ans = root;
            return ans;
        } else if(root.val == p.val && root.val == q.val) {
            ans = root;
            return ans;
        } else if(root.val == p.val || root.val == q.val) {
            return root;
        } else if((l != null || r != null)){
            return root;
        }
        return null;
    }
    
}

2. 重建二叉树

原题链接

在这里插入图片描述

根据前序遍历和中序遍历 得到树

过程如下:

  1. 首先根据前序遍历找到 根节点
  2. 找到中序遍历中,该根节点的位置
  3. 中序中 位于 根节点左边的就是 左子树,右边的就是右子树
  4. 由于我们需要在中序遍历中找到根节点的位置,那么每次都需要遍历中序遍历,不如直接用unordered_map存储数值和位置
  5. 便于写代码,我们可以每次把mp[根节点] 的位置 用变量表示出来

在这里插入图片描述

本题的代码不需要死记硬背

就需要明白

由前序确定根节点
由中序确定左右子树的个数
由左右子树的个数确定下一个根节点的位置

根据这三点去写代码即可

/**
 * 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:

    unordered_map<int,int> pos;

    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        int n = preorder.size();
        for (int i = 0; i < n; i ++ )
            pos[inorder[i]] = i;
        return dfs(preorder, inorder, 0, n - 1, 0, n - 1);
    }

    TreeNode* dfs(vector<int>&pre, vector<int>&in, int pl, int pr, int il, int ir)
    {
        if (pl > pr) return NULL;
        int k = pos[pre[pl]] - il;
        TreeNode* root = new TreeNode(pre[pl]);
        root->left = dfs(pre, in, pl + 1, pl + k, il, il + k - 1);
        root->right = dfs(pre, in, pl + k + 1, pr, il + k + 1, ir);
        return root;
    }
};

补充题:树的遍历

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

#include <iostream>
#include <string>
#include <unordered_map>
#include <vector>
#include <algorithm>
#include<memory>
using namespace std;

const  int N = 35;
int n;
int inorder[N], postorder[N];
unordered_map<int, int > leftChile, rightChile;//哈希表保存树,leftChile[i] = j: i 的左儿子是j,rightChilet同理
unordered_map<int, int > h;//保存中序遍历中各节点的位置

int dfs(int postorder[], int inorder[], int l1, int r1, int l2, int r2)//构造二叉树
{   
    if (l1 > r1) return 0;//没有节点,返回0
    int root = postorder[r1];//根结点为后续遍历的最后一个节点

    int k = h[root];//找到根节点在序遍历中的位置

    leftChile[root] = dfs(postorder, inorder, l1, k - 1 - l2 + l1, l2, k - 1);//构造左儿子
    rightChile[root] = dfs(postorder, inorder,r1-1 - (r2 - (k +1)) , r1 -1, k + 1, r2);//构造右儿子

    return root;
}

int main()
{
    cin >> n;//输入
    for (int i = 0; i < n; i++)
        cin >> postorder[i];

    for (int i = 0; i < n; i++)
    {
        cin >> inorder[i];
        h[inorder[i]] = i;//保存中序遍历中各个节点的位置
    }
    int root = dfs(postorder, inorder, 0, n - 1, 0, n - 1);//构造二叉树

    //数组模拟队列
    int q[N], hh = 0, tt = -1;//按层次遍历
    if (root)//非0 表示有节点
        q[++tt] = root;

    while (hh <= tt)
    {
        int t = q[hh++];
        if (leftChile[t]) q[++tt] = leftChile[t];//非0 为节点,入队列
        if (rightChile[t]) q[++tt] = rightChile[t];//非0 为节点,入队列
    }
    for (int i = 0; i <= tt; i++)//队列中保存的就是按层次遍历的结果
        cout << q[i] << " ";
    return 0;
}

3. 二叉树的下一个节点

原题链接

中序遍历:左根右

在这里插入图片描述

本题要分析节点的特点

  1. 如果节点有右子树,那么右子树的最左边的节点就是该节点后序
  2. 如果没有右子树,会有三种可能,在代码中有体现
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode father;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    /**
     * 模拟
     * 时间复杂度:O(height),height 为二叉树的高度
     * 空间复杂度:O(1)
     */
    public TreeNode inorderSuccessor(TreeNode p) {
        TreeNode node = p;
        // Case 1. 如果该节点有右子树,那么下一个节点就是其右子树中最左边的节点
        if (node.right != null) {
            node = node.right;
            while (node.left != null) {
                node = node.left;
            }
            return node;
        }
            
        if(node.father != null && node.father.left == node)
            return node.father;
        if(node.father != null && node.father == null)
            return null;
        while(node.father!=null && node.father.right == node)
        {
            node = node.father;
        }
        return node.father;
    }
}

4. 树的子结构( 递归中调用递归 )

原题链接
在这里插入图片描述
在这里插入图片描述

/**
 * 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:
    bool hasSubtree(TreeNode* pRoot1, TreeNode* pRoot2) {
        if (!pRoot1 || !pRoot2) return false;
        if (isSame(pRoot1, pRoot2)) return true;
        return hasSubtree(pRoot1->left, pRoot2) || hasSubtree(pRoot1->right, pRoot2);
    }

    bool isSame(TreeNode* pRoot1, TreeNode* pRoot2) {
        if (!pRoot2) return true;
        if (!pRoot1 || pRoot1->val != pRoot2->val) return false;
        return isSame(pRoot1->left, pRoot2->left) && isSame(pRoot1->right, pRoot2->right);
    }
};
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public boolean hasSubtree(TreeNode pRoot1, TreeNode pRoot2) {
        // 类比字符串匹配
        if (pRoot1 == null || pRoot2 == null) return false;
        if (isPart(pRoot1, pRoot2)) return true;
        // 如果以 pRoot1 开始的子树不能包含 pRoot2 的话,就从 pRoot1.left 和 pRoot1.right 开始
        return hasSubtree(pRoot1.left, pRoot2) || hasSubtree(pRoot1.right, pRoot2);
    }

    // 以 pRoot1 节点为根的情况下,pRoot1 和 pRoot2 同时对应遍历,如果遍历到的值都相同,且 pRoot2 先遍历到 null 或者同时遍历到 null,说明 pRoot2 是 pRoot1 的子结构
    public boolean isPart(TreeNode pRoot1, TreeNode pRoot2) {
        if (pRoot2 == null) return true;
        if (pRoot1 == null || pRoot1.val != pRoot2.val) return false;
        // 同时遍历左右子树
        return isPart(pRoot1.left, pRoot2.left) && isPart(pRoot1.right, pRoot2.right);
    }
}

5. 二叉树的镜像(两个指针互换可用 swap)

原题链接
在这里插入图片描述
在这里插入图片描述

/**
 * 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:
    void mirror(TreeNode* root) {
        if (!root) return;
        swap(root->left, root->right);
        mirror(root->left);
        mirror(root->right);
    }
};
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public void mirror(TreeNode root) {
        dfs(root);
    }
    
    public void dfs(TreeNode root){
        if(root == null){
            return;
        }
        
        TreeNode temp = root.right;
        
        root.right = root.left;
        root.left = temp;
        
        dfs(root.left);
        dfs(root.right);
        
    }
    
}

6. 对称的二叉树

原题链接
在这里插入图片描述
在这里插入图片描述

错解:通过根节点比较子节点

没写完,太复杂

/**
 * 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:
    bool isSymmetric(TreeNode* root) {
        if(root == NULL)
            return true;
        return dfs(root->left,root->right);
    }
    
    bool dfs(TreeNode* r1,TreeNode* r2)
    {
        if(r1==NULL && r2==NULL)
            return true;
        if(r1!=NULL&&r2==NULL || r1==NULL&&r2!=NULL)
            return false;
        if(r1->left->val != r2->right->val || r1->right->val != r2->left->val)
            return false;
        return dfs(r1->left,r2->right) && dfs(r1->right,r2->left);
    }
    
};

正解:比较当前节点的值即可

/**
 * 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:
    bool isSymmetric(TreeNode* root) {
        if(root == NULL)
            return true;
        return dfs(root->left,root->right);
    }
    
    bool dfs(TreeNode* r1,TreeNode* r2)
    {
        if(r1==NULL && r2==NULL)
            return true;
        if(r1!=NULL&&r2==NULL || r1==NULL&&r2!=NULL)
            return false;
        if(r1->val != r2->val)
            return false;
        return dfs(r1->left,r2->right) && dfs(r1->right,r2->left);
    }
    
};
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public boolean isSymmetric(TreeNode root) {
        
        if(root == null){
            return true;
        }
        
        return dfs(root.left,root.right);
        
    }
    
    public boolean dfs(TreeNode l,TreeNode r){
        
        if((l == null && r != null) || (l != null && r == null)){
            return false;
        }
        
        if(l == null && r == null){
            return true;
        }
        
        if(l.val != r.val){
            return false;
        }
        
        return dfs(l.left,r.right) && dfs(l.right,r.left);
        
    }
    
}

7. 不分行从上往下打印二叉树( 层序遍历二叉树bfs )

原题链接

在这里插入图片描述

/**
 * 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:
    vector<int> printFromTopToBottom(TreeNode* root) {
        vector<int> ans;
        if(root==NULL)
            return ans;
        queue<TreeNode*> q;
        q.push(root);
        while(q.size())
        {
            auto t = q.front();
            q.pop();
            ans.push_back(t->val);
            
            if(t->left != NULL)
                q.push(t->left);
            if(t->right != NULL)
                q.push(t->right);
        }
        return ans;
    }
};

8. 分行从上往下打印二叉树

( 利用两个队列遍历 )

利用数组个数 进行遍历

原题链接

在这里插入图片描述
在这里插入图片描述

/**
 * 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:
    vector<int> get_val(vector<TreeNode*> level)
    {
        vector<int> res;
        for (auto &u : level)
            res.push_back(u->val);
        return res;
    }

    vector<vector<int>> printFromTopToBottom(TreeNode* root) {
        vector<vector<int>>res;
        if (!root) return res;
        vector<TreeNode*>level;
        level.push_back(root);
        res.push_back(get_val(level));
        while (true)
        {
            vector<TreeNode*> newLevel;
            for (auto &u : level)
            {
                if (u->left) newLevel.push_back(u->left);
                if (u->right) newLevel.push_back(u->right);
            }
            if (newLevel.size())
            {
                res.push_back(get_val(newLevel));
                level = newLevel;
            }
            else break;
        }
        return res;
    }
};

9. 之字形打印二叉树

原题链接
在这里插入图片描述
本题和上一道题差不多
就是需要定义一个变量
判断是否需要翻转

/**
 * 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:
    vector<int> get_val(vector<TreeNode*> level)
    {
        vector<int> res;
        for (auto &u : level)
            res.push_back(u->val);
        return res;
    }

    vector<vector<int>> printFromTopToBottom(TreeNode* root) {
        vector<vector<int>>res;
        if (!root) return res;
        vector<TreeNode*>level;
        level.push_back(root);
        res.push_back(get_val(level));
        bool zigzag = true;
        while (true)
        {
            vector<TreeNode*> newLevel;
            for (auto &u : level)
            {
                if (u->left) newLevel.push_back(u->left);
                if (u->right) newLevel.push_back(u->right);
            }
            if (newLevel.size())
            {
                vector<int>temp = get_val(newLevel);
                if (zigzag)
                    reverse(temp.begin(), temp.end());
                res.push_back(temp);
                level = newLevel;
            }
            else break;
            zigzag = !zigzag;
        }
        return res;
    }
};
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public List<List<Integer>> printFromTopToBottom(TreeNode root) {
        
        List<List<Integer>> ans = new ArrayList<>();
        
        if(root == null){
            return ans;
        }
        
        Queue<TreeNode> q1 = new LinkedList<TreeNode>();
        q1.offer(root);
        List<Integer> l = new ArrayList();
        l.add(root.val);
        ans.add(l);
        boolean flag = false;
        while(true) {
            Queue<TreeNode> q2 = new LinkedList<TreeNode>();
            
            for(TreeNode x : q1){
                if(x.left != null) {
                    q2.offer(x.left);
                }
                if(x.right != null) {
                    q2.offer(x.right);
                }
            }
            
            if(!q2.isEmpty()) {
                List<Integer> l1 = new ArrayList();
                for(TreeNode x : q2){
                    l1.add(x.val);
                }
                if(flag == false){
                    Collections.reverse(l1);
                    flag = true;
                } else {
                    flag = false;
                }
                ans.add(l1);
                q1 = q2;
            } else {
                break;
            }
        }
        return ans;
    }
}
```java
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public List<List<Integer>> printFromTopToBottom(TreeNode root) {
        
        List<List<Integer>> ans = new ArrayList<>();
        
        if(root == null){
            return ans;
        }
        
        Queue<TreeNode> q1 = new LinkedList<TreeNode>();
        q1.offer(root);
        List<Integer> l = new ArrayList();
        l.add(root.val);
        ans.add(l);
        
        while(true) {
            Queue<TreeNode> q2 = new LinkedList<TreeNode>();
            
            for(TreeNode x : q1){
                if(x.left != null) {
                    q2.offer(x.left);
                }
                if(x.right != null) {
                    q2.offer(x.right);
                }
            }
            
            if(!q2.isEmpty()) {
                List<Integer> l1 = new ArrayList();
                for(TreeNode x : q2){
                    l1.add(x.val);
                }
                ans.add(l1);
                q1 = q2;
            } else {
                break;
            }
        }
        return ans;
    }
}

10. 二叉搜索树的后序遍历序列

原题链接
在这里插入图片描述

考点:根据二叉搜索树的后序遍历的特点

由于是后序遍历,所以最后一个结点就是根节点,又因为是二叉搜索树,所以从第一个结点开始所有比它小的结点就是它的左子树,其他就是它的右子树。如果右子树有点不大于根节点的话就说明不是一棵二叉搜索树,返回false。最后递归处理左右子树。


class Solution {
public:
    vector<int> seq;//设成全局变量方便操作

    bool verifySequenceOfBST(vector<int> sequence) {
        seq = sequence;
        return dfs(0, seq.size() - 1);
    }

    bool dfs(int l, int r)
    {
        //如果区间内啥也没有就说明把所有的结点都判断完了,却没有一个是有问题的,所以返回true
        if (l >= r)
            return true;
        //取出根节点
        int root = seq[r];
        //找出所有从l开始连续的比根节点小的结点
        int k = l;
        while (k < r && seq[k] < root)
            k ++;
        //这时k就是右子树后序遍历中的第一个结点
        //如果不满足二叉搜索树的性质就返回false
        for (int i = k; i < r; i ++)
            if (seq[i] < root)
                return false;
        //递归处理左右子树
        //y总的视频里的代码是错的
        //他写的是return dfs(l, k - 1) && dfs(k + 1, r);
        //这样会WA
        return dfs(l, k - 1) && dfs(k, r - 1);
    }
};
class Solution {
    public boolean verifySequenceOfBST(int [] sequence) {
        seq = sequence;
        return dfs(0, seq.length - 1);
    }

    private boolean dfs(int l, int r) {
        if (l >= r) return true;
        int root = seq[r];
        int k = l;
        while (k < r && seq[k] < root) k++;
        for (int i = k; i < r; i++) {
            if (seq[i] < root)
                return false;
        }
        return dfs(l, k - 1) && dfs(k, r - 1);
    }

    private int[] seq;
}

11. 二叉树中和为某一值的路径( dfs回溯 )

注意:只能是根节点到叶子节点

原题链接
在这里插入图片描述
首先补充题意:本题要求的路径是根节点到叶子节点

本题就是一个dfs回溯问题

/**
 * 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:
    
    vector<vector<int>> ans;
    
    vector<vector<int>> findPath(TreeNode* root, int sum) {
        vector<int> sup;
        dfs(root,sum,sup);
        return ans;
    }
    
    void dfs(TreeNode* root,int sum,vector<int>& sup)
    {
        if(root == NULL)
            return;
        
        sum -= root->val;
        sup.push_back(root->val);
        
        if(root->left == NULL && root->right == NULL && sum == 0)
            ans.push_back(sup);
        dfs(root->left,sum,sup);
        dfs(root->right,sum,sup);
        
        sum += root->val;
        sup.pop_back();
            
    }
    
};
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    
    public List<List<Integer>> res = new ArrayList<>();
    
    public List<List<Integer>> findPath(TreeNode root, int sum) {
        
        List<Integer> list = new ArrayList<>();
        dfs(root,list,sum,0);
        
        return res;
    }
    
    void dfs(TreeNode root,List<Integer> list,int sum,int ans){
        
        if(root == null){
            return;
        }
        
        list.add(root.val);
        
        if(ans+root.val == sum && root.left == null && root.right == null){
            res.add(new ArrayList<>(list));
        }
        
        dfs(root.left,list,sum,ans+root.val);
        dfs(root.right,list,sum,ans+root.val);
        
        list.remove(list.size() - 1);
        
    }
}

12. 序列化二叉树【序列化二叉树(本质就是 前中后序遍历)】

原题链接
在这里插入图片描述
本题就是实现两个函数

把二叉树转成 字符串形式(可以根据前序遍历 后序遍历 中序遍历 层序遍历都可以)

然后把二叉树的字符串形式 转成二叉树

前序遍历:

/**
 * 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:

    // Encodes a tree to a single string.
    string serialize(TreeNode* root) {
        string res;
        dfs_s(root, res);
        return res;
    }

    void dfs_s(TreeNode *root, string &res)
    {
        if (!root) {
            res += "null ";
            return;
        }
        res += to_string(root->val) + ' ';//int转成string就是用to_string
        dfs_s(root->left, res);
        dfs_s(root->right, res);
    }

    // Decodes your encoded data to tree.
    TreeNode* deserialize(string data) {
        int u = 0;
        return dfs_d(data, u);
    }

    TreeNode* dfs_d(string data, int &u)
    {
        if (u == data.size()) return NULL;
        int k = u;
        while (data[k] != ' ') k ++ ;
        if (data[u] == 'n') {
            u = k + 1;
            return NULL;
        }
        int val = 0, sign = 1;
        if (u < k && data[u] == '-') sign = -1, u ++ ;
        for (int i = u; i < k; i ++ ) val = val * 10 + data[i] - '0';
        val *= sign;
        u = k + 1;
        auto root = new TreeNode(val);
        root->left = dfs_d(data, u);
        root->right = dfs_d(data, u);
        return root;
    }
};

13. 二叉搜索树的第k个结点

原题链接

在这里插入图片描述

/**
 * 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 *ans;

    TreeNode* kthNode(TreeNode* root, int k) {
        dfs(root, k);
        return ans;
    }

    void dfs(TreeNode *root, int &k)
    {
        if (!k || !root) return;
        dfs(root->left, k);
        --k;
        if (!k) ans = root;
        else dfs(root->right, k);
    }
};

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public int k;
    public TreeNode kthNode(TreeNode root, int kk) {
        
        if(root == null){
            return null;
        }
        
        k = kk;
        
        return dfs(root);
    }
    
    public TreeNode dfs(TreeNode root){
        
        if(root == null || k < 0){
            return null;
        }
        
        TreeNode l = dfs(root.left);
        
        k = k - 1;
        if(k == 0){
            return root;
        }
        
        TreeNode r = dfs(root.right);
        
        if(l != null) {
            return l;
        } else if(r != null) {
            return r;
        } else {
            return null;
        }
        
    }
}

14. 二叉树的深度【二叉树递归】

原题链接
在这里插入图片描述

/**
 * 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:
    int treeDepth(TreeNode* root) {
        return dfs(root,0);
    }
    int dfs(TreeNode* r,int ans){
        if(r==NULL)
            return ans;
        ans++;
        return max(dfs(r->left,ans),dfs(r->right,ans));
    }
};
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public int treeDepth(TreeNode root) {
        return dfs(root,0);
    }
    
    public int dfs(TreeNode root,int cnt) {
        
        if (root == null) {
            return cnt;
        }
        
        int l = dfs(root.left,cnt+1);
        int r = dfs(root.right,cnt+1);
        
        if (l > r) {
            return l;
        } else {
            return r;
        }
        
    }
    
}

15. 平衡二叉树【二叉树递归】

原题链接
在这里插入图片描述

/**
 * 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:

    bool ans = true;

    bool isBalanced(TreeNode* root) {
        dfs(root);
        return ans;
    }

    int dfs(TreeNode *root)
    {
        if (!root) return 0;
        int left = dfs(root->left), right = dfs(root->right);
        if (abs(left - right) > 1) ans = false;
        return max(left, right) + 1;
    }
};
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    
    boolean flag = true;
    
    public boolean isBalanced(TreeNode root) {
        dfs(root,0);
        return flag;
    }
    
    public int dfs(TreeNode root,int cnt) {
        
        if (root == null) {
            return cnt;
        }
        
        int l = dfs(root.left,cnt+1);
        int r = dfs(root.right,cnt+1);
        
        if (l - r >= 2) {
            flag = false;
        }
        
        if (l > r) {
           return l; 
        } else {
            return r;
        }
        
    }
    
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/916764.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

解密七夕节快递速度之谜:物流行业的幕后功臣

又是一年七夕&#xff0c;今年爱情总是伴随着太多的不确定性&#xff0c;突然的通知、滞留的快递、延期的演出...在这个特殊的日子里&#xff0c;大多数人都会选择通过网购礼物传递爱意和祝福。在此&#xff0c;快递物流就扮演着至关重要的角色。 在七夕节前后&#xff0c;快递…

解决政务审计大数据传输难题!镭速传输为政务行业提供解决方案

政务行业是国家治理的重要组成部分&#xff0c;涉及到国家安全、社会稳定、民生福祉等方面。随着信息技术的快速发展和革新&#xff0c;政务信息化也迎来了新一轮的升级浪潮。国家相继出台了《国家信息化发展战略纲要》《“十三五”国家信息化规划》《“十四五”推进国家政务信…

新生开学必备攻略|开学必备数码产品清单合集

​新学期将至&#xff0c;有哪些需要准备的东西呢&#xff1f;知道大家都正在为摊开的行李箱发愁&#xff0c;小篇特地整理了一份开学必备的《开学数码产品清单合集》&#xff0c;来抄作业吧&#xff0c;各位&#xff01; 推荐一&#xff1a;南卡00压蓝牙耳机 不入耳设计&…

Vue2学习笔记のvuex

目录 vuex1.概念2.何时使用&#xff1f;3.搭建vuex环境4.基本使用5.getters的使用6.四个map方法的使用7.模块化命名空间 hello, 本文是Vue2学习笔记的第5篇&#xff1a;vuex。 vuex 1.概念 在Vue中实现集中式状态&#xff08;数据&#xff09;管理的一个Vue插件&#xff0c;对…

有些网络通信协议? - 易智编译EaseEditing

网络通信协议是计算机网络中用于实现数据传输和通信的规则和标准。以下是一些常见的网络通信协议&#xff1a; TCP/IP协议&#xff1a; 是互联网的核心协议&#xff0c;包括传输控制协议&#xff08;TCP&#xff09;和网际协议&#xff08;IP&#xff09;。TCP负责数据的可靠传…

Linux 计算机网络基础概论

一、网络基本概念 1、网络 网络是由若干节点和连接这些结点的链路组成&#xff0c;网络中的结点可以是计算机、交换机、路由器等设备。通俗地说就是把不同的主机连接起来就构成了一个网络&#xff0c;构成网路的目的是为了信息交互、资源共享。 网络设备有&#xff1a;交换机…

数字化浪潮中的稳定之锚:项目敏捷性与灵活性的秘密

引言 在这个日新月异的数字化时代&#xff0c;企业和团队面临着前所未有的挑战。技术的快速发展、客户需求的不断变化以及全球化的竞争环境都要求我们重新思考项目管理的方法。在这样的背景下&#xff0c;敏捷性和灵活性成为了项目成功的关键。 当前数字化时代的挑战与机遇 …

Mimikatz免杀实战:绕过360核晶和defender

文章目录 前言绕过360核晶实现思路完整代码运行测试 绕过WD实现思路MiniDumpWriteDump回调函数加密dump文件 完整代码运行测试 参考文章 前言 通常来说&#xff0c;即使我们成功实现了mimikatz的静态免杀&#xff0c;其抓取hash的行为仍可能会被防病毒软件检测到虽然你可以通过…

基于VUE3+Layui从头搭建通用后台管理系统(前端篇)十:实体配置功能实现

一、本章内容 本章实现实体配置功能,包括识别实体属性、设置各属性的展示方式、相关类型、要和展示、编辑的内容等。 1. 详细课程地址: 待发布 2. 源码下载地址: 待发布 二、界面预览 三、开发视频 3.1 B站视频地址:

与ChatGPT可以经常互动但也不要暴露自己

​ 全球亿万人使用ChatGPT&#xff0c;但这并不意味着你的个人信息数据就可以安全无忧。要特别注意的&#xff0c;而且很多人已经忽视了的&#xff1a;用户最好不要过多地提供有关自己的私密信息&#xff0c;虽然多数情况下你并不知道自己是怎么把信息泄露的。 首先&#xff0…

绝美的古诗词AI作画,惊艳到我了!

前言 时光荏苒&#xff0c;科技的飞速发展催生出了许多令人惊叹的创新成果。近年来&#xff0c;人工智能技术在艺术领域的应用日益引人注目&#xff0c;其中最为引人瞩目的莫过于AI作画。这项技术将传统的古诗词与现代的人工智能相结合&#xff0c;创造出一幅幅令人叹为观止的…

Godot 4.0 文件系统特性的总结

文件的路径和特点(常规知识) 这一部分官方文档讲得比较详细,我这里简单提一下。 Godot会对文件进行组织,从而将它们管理起来,引擎的使用者要访问被管理的文件,需要遵循这样的规定: 使用Godot提供的函数和类访问文件 个人发现常用的有这些: ResourceLoader类、GD.Load()、God…

Jenkins的定时任务配置

jenkins配置定时任务位置(点击日程表的问好可查看语法配置) jenkins的定时任务的参数 # 定时任务参数(每个参数之间使用tab键或空格分隔)MINUTE HOUR DOM MONTH DOW 参数解释取值范围 MINUTE 分钟0-59HOUR小时0-23DOM一月的天数1-31MONTH月份1-12DOW 一周的天数0…

2023.8 - java - StringBuffer 和 StringBuilder 类

当对字符串进行修改的时候&#xff0c;需要使用 StringBuffer 和 StringBuilder 类。 注意:String 类是不可改变的&#xff0c;所以你一旦创建了 String 对象&#xff0c;那它的值就无法改变了 如果需要对字符串做很多修改&#xff0c;那么应该选择使用 StringBuffer & S…

【LeetCode-中等题】438. 找到字符串中所有字母异位词

题目 题解一&#xff1a;暴力排序 依次截取三为排序好的字符串拿出来比较 // 方法一&#xff0c;暴力排序List<Integer> res new ArrayList<Integer>();int n s.length();int k p.length();if (n < k) {return res;}char[] chars p.toCharArray();Arrays.s…

软件配置安装(破解)--- maven下载配置

检查环境是否已有 首先检查一下电脑里有无maven环境&#xff0c;有的话就不用安装了 查看path环境中没有maven&#xff0c;开始准备接下来的重头戏 下载maven 下载bin.zip版 解压mavenxxxbin.zip &#xff08;建议把解压的文件放在一个文件夹内&#xff0c;命名英文的env…

基于Redis的BitMap实现签到、连续签到统计(含源码)

微信公众号访问地址&#xff1a;基于Redis的BitMap实现签到、连续签到统计(含源码) 推荐文章&#xff1a; 1、springBoot对接kafka,批量、并发、异步获取消息,并动态、批量插入库表; 2、SpringBoot用线程池ThreadPoolTaskExecutor异步处理百万级数据; 3、基于Redis的Geo实现附…

数字 IC 设计职位经典笔/面试题(三)

共100道经典笔试、面试题目&#xff08;文末可全领&#xff09; 1. IC 设计中同步复位与异步复位的区别&#xff1f; 同步复位在时钟沿变化时&#xff0c;完成复位动作。异步复位不管时钟&#xff0c;只要复位信号满足条件&#xff0c;就完成复位动作。异步复位对复位信号要求…

coco数据集制作-多文件夹

背景&#xff1a;标准的coco格式数据集需要把所有图片放到一个文件夹里&#xff0c;而很多情况下&#xff0c;会有很多个文件夹&#xff0c;我们并不想把所有图片放到一起。 本文把多个文件夹下的yolov8(5)的txt标签转换至coco标签&#xff0c;转换标签代码如下&#xff1a; …

ipad可以用别的品牌的手写笔吗?开学平价电容笔推荐

开学需要买什么呢&#xff1f;随着科技的不断进步&#xff0c;各种类型的iPad电容笔应运而生。一支好的电容笔&#xff0c;不仅能大大提高我们的工作效率&#xff0c;而且能大大提高我们的生产力。平替的这款电容笔&#xff0c;不管是在技术上&#xff0c;还是在品质上&#xf…