zoukankan      html  css  js  c++  java
  • 二叉树

    1. 二叉树构建(通过完全二叉树数组)

    Node* build_tree(int* t, int n, int i)
    {
        if (i > n || t[i - 1] < 0) return nullptr;
        Node* pl = build_tree(t, n, i * 2);
        Node* pr = build_tree(t, n, i * 2 + 1);
        return new Node(t[i - 1], pl, pr);
    }
    
    void pre(Node* t)
    {
        if(!t) return;
        cout << t->value << endl;
        pre(t->left);
        pre(t->right);
    }
    
    int t[7] = { 5, 1, 4, -1, -1, 3, 6}; // -1为空
    Node* tree = build_tree(t, 7, 1); // 创建二叉树,第三个参数为1
    pre(tree);
    //    5
    //   / 
    //  1   4
    //     / 
    //    3   6
    

    2. 翻转二叉树

    // 把树所有节点的左右都翻转
    TreeNode* inverse(TreeNode* root)
    {
        if (!root) return nullptr;
        swap(root->left, root->right);
        inverse(root->left);
        inverse(root->right);
        return root;
    }
    

    3. Leetcode 98. 验证二叉搜索树

    假设一个二叉搜索树具有如下特征:
    节点的左子树只包含小于当前节点的数。
    节点的右子树只包含大于当前节点的数。
    所有左子树和右子树自身必须也是二叉搜索树。
    输入:
        5
       / 
      1   4
         / 
        3   6
    输出: false
    解释: 输入为: [5,1,4,null,null,3,6]。
         根节点的值为 5 ,但是其右子节点值为 4 。
    
    class Solution {
    public:
        bool isValidBST(TreeNode* root) {
            long min_value, max_value; bool valid;
            dfs(root, &min_value, &max_value, &valid);
            return valid;
        }
        void dfs(TreeNode* root,  // 全部用指针传递结果
            long *min_val, long *max_val, bool *valid) {
            
            // 边界处理
            if (root==nullptr) {
                *min_val = LONG_MAX;
                *max_val = LONG_MIN;
                *valid = true;
                return;
            }
            
            // 搜索
            long l_min_val, l_max_val; bool l_valid;
            dfs(root->left, &l_min_val, &l_max_val, &l_valid);
            long r_min_val, r_max_val; bool r_valid;
            dfs(root->right, &r_min_val, &r_max_val, &r_valid);
    
            // 值传递
            if(l_max_val<root->val&&r_min_val>root->val)
                *valid = l_valid && r_valid;
            else *valid = false;
            *max_val = max(r_max_val, (long)root->val);
            *min_val = min(l_min_val, (long)root->val);
        }
    };
    

    4. 判断是否是平衡二叉树

    bool isBalance(TreeNode* root, int* depth)
    {
        if (!root) {
            *depth = 0; // 记录深度
            return true;
        }
        int ld, rd;
        if (isBalance(root->left, &ld) && isBalance(root->right, &rd)) {
            if (abs(ld - rd) <= 1) {
                *depth = 1 + (ld > rd ? ld : rd);
                return true;
            }
        }
        return false;
    }
    

    5. 二叉树k层节点个数

    int getkNum(Node* root, int k)
    {
        if (!root || k <= 0) return 0;
        if (k == 1) return 1;
        return getkNum(root->left, k - 1) + getkNum(root->right, k - 1);
    }
    

    6. 二叉树找最近公共祖先

    // 非常非常经典,建议背出
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if(root==NULL || root==p || root==q) return root; // 要么是NULL,要么是p或q
        // 向左(右)找p或q,找到返回p或q或公共祖先,找不到返回NULL
        TreeNode *left = lowestCommonAncestor(root->left, p, q);
        TreeNode *right = lowestCommonAncestor(root->right, p, q);
        if(left!=NULL && right!=NULL) return root; // 两边都找到,root肯定是最近公共祖先
        else return left!=NULL?left:right; 
        // 因为假设必须存在公共祖先,所以递归的最上层必须会返回公共祖先,而不是p或q
    }
    

    7. 二叉树中最大路径和

    题目: https://leetcode-cn.com/problems/binary-tree-maximum-path-sum/
    类似动态规划方法,只是用到了回溯
    
    int find(TreeNode *root, int &maxm) {
        if(root==NULL) return 0;
        int left_max = find(root->left, maxm);
        int right_max = find(root->right, maxm);
        maxm = max(maxm, left_max+root->val+right_max);
        int res = max(left_max, right_max) + root->val;
        return max(0, res);
    }
    int maxPathSum(TreeNode* root) {
        int maxm=-999999999;
        find(root, maxm);
        return maxm;
    }
    

    8. 二叉树中序非递归

    // 直接背
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> res;
        stack<TreeNode*> st;
        auto p = root;    
        while (p || !st.empty()) { // p和st必须全部清空才能退出
            // 第一步,向左一条路走到黑
            while (p) {
                st.push(p);
                p = p->left;
            }
            // 第二步,退栈向右试探
            auto node = st.top();
            st.pop();
            res.emplace_back(node->val);
            p = node->right;
        }   
        return res;
    }
    

    9. 二叉树的直径

    给定一棵二叉树,你需要计算它的直径长度。
    一棵二叉树的直径长度是任意两个结点路径长度中的最大值。
    这条路径可能穿过也可能不穿过根结点。
    
    给定二叉树
              1
             / 
            2   3
           /      
          4   5    
    返回 3, 它的长度是路径 [4,2,1,3] 或者 [5,2,1,3]。
    这道题与 7 题类似
    
    int find(TreeNode *root, int &maxm) {
        if(root==NULL) return 0;
        int left_max = find(root->left, maxm);
        int right_max = find(root->right, maxm);
        maxm = max(maxm, left_max + right_max);
        return max(left_max, right_max) + 1;
    }
    int diameterOfBinaryTree(TreeNode* root) {
        int maxm=0;
        find(root, maxm);
        return maxm;
    }
    

    10. 二叉树之字形遍历

    // 层次遍历,奇数层逆序输出
    // 下面这个代码很好地展现了层次遍历,并记录层次编号的方案
    vector<vector<int>> zigzagLevelOrder(TreeNode* root) {
        vector<vector<int>> res;
        queue<TreeNode*> q;
        if (root) q.push(root);
        bool lr = true;
        while (!q.empty()) {
            int size = q.size(); // 先查看size,再按size压入
            vector<int> level(size, 0);
            while (size--) {
                root = q.front(); q.pop();
                level[lr ? level.size() - size - 1 : size] = root->val;
                if (root->left) q.push(root->left);
                if (root->right) q.push(root->right);
            }
            res.push_back(level);
            lr = !lr;
        }
        return res;
    }
    

    11. 二叉搜索树插入

    TreeNode* insertIntoBST(TreeNode* root, int val) {
        // 直接插在最后面
        if(!root) return new TreeNode(val);
        if(root->val < val) root->right = insertIntoBST(root->right, val);
        else root->left = insertIntoBST(root->left, val);
        return root;
    }
    

    12. 二叉搜索树删除

    // 非常漂亮!!必背!!
    TreeNode* deleteNode(TreeNode* root, int key) {
        if(!root) return root;
        if(key<root->val)root->left=deleteNode(root->left,key);
        if(key>root->val)root->right=deleteNode(root->right,key);
        if(key==root->val){
            if(!root->left&&!root->right)return NULL;
            if(root->left&&!root->right)return root->left;
            if(!root->left&&root->right)return root->right;
            // 用中序下一个节点值替换,然后再递归删后面的
            TreeNode* temp=root->right;
            while(temp->left)temp=temp->left;
            root->val=temp->val;
            root->right=deleteNode(root->right,root->val);
        }
        return root;
    }
    

    13. 二叉树最大宽度

    给定一个二叉树,编写一个函数来获取这个树的最大宽度。
    树的宽度是所有层中的最大宽度。
    这个二叉树与满二叉树(full binary tree)结构相同,但一些节点为空。
    
    每一层的宽度被定义为两个端点(该层最左和最右的非空节点,两端点间的null节点也计入长度)之间的长度。
    
    输入: 
    
               1
             /   
            3     2
           /        
          5   3     9 
    
    输出: 4
    解释: 最大值出现在树的第 3 层,宽度为 4 (5,3,null,9)。
    
    int widthOfBinaryTree(TreeNode* root) {
        vector<int> level_first_index;
        int maxw=0;
        dfs(root, 1, 1, level_first_index, maxw);
        return maxw;
    }
    // dfs就能传树节点在完全二叉树上的index
    void dfs(TreeNode *root, int level, int index, 
        vector<int> &level_first_index, int &maxw)
    {
        if(!root) return;
        // 关键:记录第一个到达level深度的节点index
        if(level>level_first_index.size()) level_first_index.push_back(index);
        maxw = max(maxw, index-level_first_index[level-1]+1);
        dfs(root->left, level+1, index*2, level_first_index, maxw);
        dfs(root->right, level+1, index*2+1, level_first_index, maxw);
    }
    

    14. 判断是否是二叉搜索树的后序序列

    // 经典分治做法
    bool verifyPostorder(vector<int>& postorder) {
        if(postorder.size() == 0)return true;
        int end = postorder.size() - 1;
        return judge(postorder, 0, end);
    }
    bool judge(vector<int> &postorder, int begin , int end){
        //只剩一个节点直接返回true
        if(begin >= end) return true;
        int i = begin , index = 0;
        //找到序列中比最右侧结点值大的那个结点
        for(; i < end ; i++) if(postorder[i] >= postorder[end]) break;
        //分治之前要满足的条件
        index = i ;
        while(i < end) if(postorder[i++] < postorder[end]) return false;
        //左右两边进行分治
        return judge(postorder, begin , index - 1) && judge(postorder , index , end - 1);
    }
    

    15. 判断树t是不是树s的子树

    class Solution {
    public:
        bool isSametree(TreeNode* s, TreeNode* t) {
            if(!s&&!t) return true;
            if(!s||!t) return false;
            if(s->val == t->val) {
                return isSametree(s->left, t->left) && isSametree(s->right, t->right);
            }
            else return false;
        }
        bool isSubtree(TreeNode* s, TreeNode* t) {
            if(!s&&!t) return true;
            if(!s||!t) return false;
            return isSametree(s, t) || isSubtree(s->left, t) || isSubtree(s->right, t);
        }
    };
    

    16. 先序中序构建二叉树

    BitTree *createBinTreeByPreIn(char *preOrder,char *inOrder,int number)
    {
        if(number==0)  return NULL; // 边界条件仅为长度为0
        char c = preOrder[0]; // 先序第一个
        int i = 0;
        while(i<number && inOrder[i]!=c) i++; // 找到它在中序中的位置
        int leftNumber = i; // 确定左右的长度
        int rightNumber = number - i - 1;
        BitTree *node = (BitTree *)malloc(sizeof(BitTree)); // 创建节点
        node->data = c;
        node->lchild = createBinTreeByPreIn(&preOrder[1], &inOrder[0], leftNumber);
        node->rchild = createBinTreeByPreIn(&preOrder[leftNumber+1], 
            &inOrder[leftNumber+1], rightNumber);
        return node;
    }
    
  • 相关阅读:
    Redis使用小结
    MongoDB中的变更通知
    发布一个从迅雷下载字幕的小工具
    在Windows下通过netsh命令实现端口映射
    .net core在Linux ARM板上运行
    通过WinAPI播放PCM声音
    spring中scope作用域(转)
    Spring <context:annotation-config/> 解说(转)
    Jenkins+Maven+SVN快速搭建持续集成环境(转)
    maven中跳过单元测试(转)
  • 原文地址:https://www.cnblogs.com/xytpai/p/13891391.html
Copyright © 2011-2022 走看看