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

二叉树

  • 二叉树
    • 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 
#include 
#include 
#include 
#include 
#include
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> res = new ArrayList<>();
    
    public List> findPath(TreeNode root, int sum) {
        
        List list = new ArrayList<>();
        dfs(root,list,sum,0);
        
        return res;
    }
    
    void dfs(TreeNode root,List 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. 序列化二叉树【序列化二叉树(本质就是 前中后序遍历)】

原题链接
《剑指Offer》模块2 二叉树【15道二叉树帮助你掌握二叉树】_第1张图片
本题就是实现两个函数

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

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

前序遍历:

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

你可能感兴趣的:(《剑指Offer》,数据结构,算法)