二叉树

作者: juriau | 来源:发表于2020-02-28 20:18 被阅读0次

    一、目录

    DFS

    • 144.二叉树的前序遍历
    • 145.二叉树的后序遍历(hard)
    • 104.二叉树的最大深度
    • 111.二叉树的最小深度
    • 100.相同的树
    • 226.翻转二叉树
    • 112.路径总和
    • 257.二叉树的所有路径
    • 437.路径总和 III
    • 剑指 Offer 26. 树的子结构
    • 543.二叉树的直径
    • 110.平衡二叉树
    • 剑指 Offer 68 - II 二叉树的最近公共祖先
    • 105. 从前序与中序遍历序列构造二叉树

    BFS

    • 102.二叉树的层序遍历
    • 111.二叉树的最小深度
    • 199.二叉树的右视图
    • 103.二叉树的锯齿形层次遍历

    二叉搜索树

    • 二叉搜索树的第k大节点
    • 判断数组是不是二叉搜索树的后序遍历结果
    • 将二叉搜索树转换为双向链表

    二、题目

    144.二叉树的前序遍历

    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> res;
        stack<TreeNode*> s;
        while (root || !s.empty()) {
            if (root) {
                s.push(root);
                res.push_back(root->val);
                root = root->left;
            }else{
                root = s.top(); s.pop();
                root = root->right;
            }
        }
        return res;
    }
    

    145.二叉树的后序遍历

    思路:需要用到两个栈。

    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> res;
        if(!root) return res;
    
        stack<TreeNode*> s1;
        stack<TreeNode*> s2;
        // 中左右
        while (root || !s1.empty()) {
            if (root) {
                s1.push(root);
                s2.push(root);
                root = root->right;
            }else{
                root = s1.top(); s1.pop();
                root = root->left;
            }
        }
        // 左右中
        while (!s2.empty()) {
            res.push_back(s2.top()->val); s2.pop();
        }
        return res;
    }
    

    104.二叉树的最大深度

    int maxDepth(TreeNode* root) {
        if (!root) return 0;
    
        int a = maxDepth(root->left);
        int b = maxDepth(root->right);
        
        return max(a, b) + 1;
    }
    

    111.二叉树的最小深度

    考虑[1,2]这种情况

    int minDepth(TreeNode* root) {
        if (!root) return 0;
        
        int a = minDepth(root->left);
        int b = minDepth(root->right);
        
        if (a==0 || b==0) return a + b + 1;
        
        return min(a, b) + 1;
    }
    

    100.相同的树

    bool isSameTree(TreeNode* p, TreeNode* q) {
        if (!p && !q) return true;
        if (!p || !q) return false;
        if (p->val != q->val) return false;
        
        return isSameTree(p->left, q->left) && isSameTree(p->right, q->right);
    }
    

    226.翻转二叉树

    思路1:创建新二叉树

    TreeNode* invertTree(TreeNode* root) {
        if (!root) return NULL;
        
        TreeNode* node = new TreeNode(root->val);
        
        node->left = invertTree(root->right);
        node->right = invertTree(root->left);
        
        return node;
    }
    

    思路2:原地改变二叉树
    注意:返回值也可以不管,不要因此而影响思路;当然也可以另外写一个函数去执行逻辑。

    TreeNode* invertTree(TreeNode* root) {
        if (!root) return NULL;
        
        swap(root->left, root->right);
        
        invertTree3(root->right);
        invertTree3(root->left);
        
        return root;
    }
    

    112.路径总和

    题目描述:从根节点到叶子节点的路径的和等于sum

    bool hasPathSum(TreeNode* root, int sum) {
        if (!root) return false;
        
        sum -= root->val;
        
        if (!root->left && !root->right){
            return sum==0;
        }
        return hasPathSum(root->left, sum) || hasPathSum(root->right, sum);
    }
    

    257.二叉树的所有路径

    void dfs(TreeNode* node, string path, vector<string>& ans){
        path += to_string(node->val);
        
        if (!node->left && !node->right) {
            ans.push_back(path);
        }else{
            path += "->";
            if (node->left) dfs(node->left, path, ans);
            if (node->right) dfs(node->right, path, ans);
        }
    }
    
    vector<string> binaryTreePaths(TreeNode* root) {
        vector<string> ans;
        if (!root) return ans;
        string path;
        dfs(root, path, ans);
        return ans;
    }
    

    437.路径总和 III

    题目描述:找出路径和等于给定数值的路径总数。路径不需要从根节点开始,也不需要在叶子节点结束,但是路径方向必须是向下的.

    思路:双层dfs。

    int count = 0;
    // 遍历以该结点为首的树
    void dfs2(TreeNode* node, int sum){
        if (!node) return;
        
        sum -= node->val;
        if (sum == 0) {
            count++;
        }
        dfs2(node->left, sum);
        dfs2(node->right, sum);
        
    }
    // 遍历整个树
    void dfs(TreeNode* node, int sum){
        if (!node) return;
        
        dfs2(node, sum);
        dfs(node->left, sum);
        dfs(node->right, sum);
    }
    
    int pathSum(TreeNode* root, int sum) {
        dfs2(root, sum);
        return count;
    }
    

    剑指 Offer 26. 树的子结构

    bool helper(Node* node1, Node* node2){
        if (!node2) return true;
        if (!node1) return false;
        if (node1->val != node2->val) return false;
        return helper(node1->left, node2->left) && helper(node1->right, node2->right);
    }
    
    bool isSubStructure(struct TreeNode* A, struct TreeNode* B){
        if (!A || !B) return false;
        
        if (helper(A, B)) return true;
        return isSubStructure(A->left, B) || isSubStructure(A->right, B);
    }
    

    543.二叉树的直径

    思路:在求最大深度的DFS过程中判断。

    int maxDepth = 0;
    int helper(TreeNode* node){
        if (!node) return 0;
        
        int a = helper(node->left);
        int b = helper(node->right);
        maxDepth = max(a+b , maxDepth);
        return max(a, b) + 1;
    }
    int diameterOfBinaryTree(TreeNode* root) {
        if (!root) return 0;
        helper(root);
        return maxDepth;
    }
    

    110.平衡二叉树

    思路:在求最大深度的DFS过程中判断。

    int helper(TreeNode* root){
        if(!root) return 0;
        
        int left = helper(root->left);
        int right = helper(root->right);
        
        if (abs(left - right) > 1 || left == -1 || right == -1) {
            return -1;
        }
        return max(left, right) + 1;
    }
    
    bool isBalanced(TreeNode* root) {
        return helper(root) != -1;
    }
    

    剑指 Offer 68 - II 二叉树的最近公共祖先

    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) return left;
        if (right) return right;
        
        return NULL;
    }
    

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

    struct TreeNode* buildTree(int* inorder, int inorderSize, int* postorder, int postorderSize){
        if (inorderSize < 1) return NULL;
    
        int rootVal = postorder[postorderSize-1];
        Node* root = (Node*)malloc(sizeof(Node));
        root->val = rootVal;
        
        // 左子树的长度
        int leftLens = 0;
        while (inorder[leftLens] != rootVal) leftLens++;
        
        // 右子树的长度
        int rightLens = inorderSize - leftLens - 1;
        
        root->left =  buildTree(inorder, leftLens, postorder, leftLens);
        root->right = buildTree(inorder+leftLens+1, rightLens, postorder+leftLens, rightLens);
        return root;
    }
    

    102.二叉树的层序遍历

    vector<vector<int>> levelOrder(TreeNode* root) {
        vector<vector<int>> res;
        if(!root) return res;
        
        queue<TreeNode*> q;
        q.push(root);
        while (!q.empty()) {
            vector<int> temp;
            int lens = q.size();
            for(int i=0; i<lens; i++){
                TreeNode* node = q.front(); q.pop();
                temp.push_back(node->val);
                if (node->left)  q.push(node->left);
                if (node->right) q.push(node->right);
            }
            res.push_back(temp);
        }
        return res;
    }
    

    111.二叉树的最小深度

    
    

    199.二叉树的右视图

    vector<int> rightSideView(TreeNode* root) {
        vector<int> ans;
        if (!root) return ans;
        
        queue<TreeNode*> que;
        que.push(root);
        while (!que.empty()) {
            int size = que.size();
            for (int i=0; i<size; i++) {
                TreeNode* node = que.front(); que.pop();
                
                if (node->left) que.push(node->left);
                if (node->right) que.push(node->right);
                if (i == size-1) {
                    ans.push_back(node->val);
                }
            }
        }
        return ans;
    }
    

    103.二叉树的锯齿形层次遍历

    vector<vector<int>> zigzagLevelOrder(TreeNode* root) {
        vector<vector<int>> ret;
        if (!root) return ret;
        
        queue<TreeNode*> que;
        que.push(root);
        int col = 0;
        while (!que.empty()) {
            col++;
            int size = que.size();
            vector<int> temp;
            stack<int> st;
            while (size--) {
                TreeNode* node = que.front(); que.pop();
                
                if (col % 2 == 0) {
                    st.push(node->val);
                }else{
                    temp.push_back(node->val);
                }
                
                if (node->left) que.push(node->left);
                if (node->right) que.push(node->right);
            }
            while (!st.empty()) {
                temp.push_back(st.top()); st.pop();
            }
    
            ret.push_back(temp);
        }
        return ret;
    }
    

    二叉搜索树的第k大节点

    思路:右根左DFS

    void visit(struct TreeNode* root, int* k, int* ret){
        if (!root || *k <0) return;
        
        visit(root->right, k, ret);
        (*k)--;
        if (*k == 0) {
            *ret = root->val;
            return;
        }
        visit(root->left, k, ret);
    }
    
    int kthLargest(struct TreeNode* root, int k){
        int ret = 0;
        visit(root, &k, &ret);
        return ret;
    }
    

    判断数组是不是二叉搜索树的后序遍历结果

    bool verifyPostorder(int* postorder, int lens){
        if (lens<=1) return true;
        
        int rootVal = postorder[lens-1];
        
        int leftLens = 0;
        while (postorder[leftLens]<rootVal) leftLens++;
        
        for (int i=leftLens; i<lens-1; i++) {
            if (postorder[i] < rootVal) {
                return false;
            }
        }
        return verifyPostorder(postorder, leftLens) && verifyPostorder(postorder+leftLens, lens-leftLens-1);
    }
    

    将二叉搜索树转换为双向链表

    class Solution {
    public:
        Node *head, *pre;
        Node* treeToDoublyList(Node* root) {
            if (!root) return nullptr;
            head = nullptr;
            dfs(root);
            head->left = pre, pre->right = head;
            return head;
        }
    
        void dfs(Node* root) {
            if (!root) return;
            dfs(root->left);
            if (!head) head = root, pre = root;
            else pre->right = root, root->left = pre, pre = root;
            dfs(root->right);
        }
    };
    

    相关文章

      网友评论

          本文标题:二叉树

          本文链接:https://www.haomeiwen.com/subject/rumxhhtx.html