二叉树习题整理(1)

1.leetcode98.验证二叉搜索树

class Solution {
     
public:
	//根节点的取值范围是minv~maxv。long long防int溢出。
    bool dfs(TreeNode* root, long long minv, long long maxv){
     
        if(!root) return true;
        if(root->val < minv || root->val > maxv) return false;
        //左树根节点严格小于root->val。取值minv~root->val-1
        //右树根节点严格大于root->val。取值root->val+1~maxv
        return dfs(root->left, minv, root->val-1ll) && dfs(root->right, root->val+1ll, maxv);
    }

    bool isValidBST(TreeNode* root) {
     
        return dfs(root, INT_MIN, INT_MAX);   
    }
};

2. leetcode101. 对称二叉树

class Solution {
     
public:

    bool dfs(TreeNode* l, TreeNode* r){
     
        //l 和 r同时为真,不执行。同时为假,返回真
        if(!l || !r) return !l && !r;
        //递归的两节点值相等
        //左树的左树值等于右树的右树,左树的右树值等于右树的左树
        return l->val==r->val && dfs(l->left, r->right) && dfs(l->right, r->left);
    }

    bool isSymmetric(TreeNode* root) {
     
        if(!root) return true;
        return dfs(root->left, root->right);
    }
};

3.leetcode94.迭代实现中序遍历

class Solution {
     
public:
    vector<int> inorderTraversal(TreeNode* root) {
     
        vector<int> ans;
        stack<TreeNode*> stk;
        TreeNode* p = root;
        while(stk.size() || p){
     
            while(p){
     
                stk.push(p);
                p = p->left;
            }
            p = stk.top(); stk.pop();
            ans.push_back(p->val);
            p = p->right;
        }
        return ans;
    }
};

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

class Solution {
     
public:
    vector<int> pre, in;
    //此题说明元素各不相同,pos存放中序序列中每个值的下标
    unordered_map<int, int> pos;
	//用pre的[pl, pr], in的[il, ir]进行建树
    TreeNode* dfs(int pl, int pr, int il, int ir) {
     
    	//r为根节点值,k为根节点在中序序列中的位置
        int r = pre[pl], k = pos[r];
        auto root = new TreeNode(r);
        //中序序列分为两部分左子树【il,k-1】,右子树【k+1,ir】
        //前序序列也被分成两部分,且长度与中序的两部分相等
        //若存在左树
        if(il <= k-1) root->left = dfs(pl+1, pl+1+k-1-il, il, k-1);
        //若存在右树
        if(k+1 <= ir) root->right = dfs(pl+k-il+1, pr, k+1, ir);
        return root;
    }

    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
     
        if(preorder.empty() || inorder.empty()) return NULL;
        pre = preorder, in = inorder;
        for(int i = 0; i < in.size(); i ++)
            pos[in[i]] = i;
        return dfs(0, pre.size()-1, 0, in.size()-1);\
    }
};

5.leetcode102. 二叉树的层序遍历

可通过在每遍历完一层在队列后面添加一个空指针的方式代表一层的结束。一定要添加条件判断if(q.size()) q.push(NULL);最后一层遍历完后不添加空指针。

class Solution {
     
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
     
        vector<vector<int>> ans;
        vector<int> path;
        if(!root) return ans;
        queue<TreeNode*> q;
        q.push(root);
        q.push(NULL);
        while(q.size()){
     
            auto t = q.front(); q.pop();
            if(t) {
     
                path.push_back(t->val);
                if(t->left) q.push(t->left);
                if(t->right) q.push(t->right);
            }
            else{
     
                ans.push_back(path);
                path.clear();
                if(q.size()) q.push(NULL);
            }
        }
        return ans;
    }
};

6.leetcode236. 二叉树的最近公共祖先

class Solution {
     
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
     
        // 若root子树中含有p(q),则返回p(q)
        // 若一边有p,令一边有q,root是最深公共祖先
        // 若一边有p和q, 一边没有,则返回的是最深公共祖先
        if(!root || root==q || root==p) return root;
        auto l = lowestCommonAncestor(root->left, p, q);
        auto r = lowestCommonAncestor(root->right, p, q);
        if(l && r) return root;
        else if(l) return l;
        else return r;
    }
};

7.leetcode543. 二叉树的直径

左树和右树的高度和即为经过此根节点的最大长度

class Solution {
     
public:
    int ans;
    int getHeight(TreeNode* root){
     
        if(!root) return 0;
        int l = getHeight(root->left);
        int r = getHeight(root->right);
        //左树和右树的高度和即为经过此根节点的最大长度
        ans = max(ans, l + r);
        return max(l, r) + 1 ;
    }

    int diameterOfBinaryTree(TreeNode* root) {
     
        getHeight(root);
        return ans;
    }
};

8.leetcode124. 二叉树中的最大路径和

/**
 * 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 ans = INT_MIN;
    //dfs求从root这点出发到它的任意孩子(向下走)的最大路径和
    int dfs(TreeNode* root){
     
        if(!root) return 0;
        int l = dfs(root->left), r = dfs(root->right);
        l = l > 0? l : 0, r = r > 0? r : 0;
        //枚举每个节点的最大路径和
        //以此点为最高点的最大路径必然是res和左树、右树都走的最大值
         ans = max(ans, l + r + root->val);
        //一个点向下走的最大路径应是以下三种情况之一
        //往左走、往右走、不走
        return max(l, r) + root->val;
    }
    int maxPathSum(TreeNode* root) {
     
        dfs(root);
        return ans;
    }
};

9.leetcode173. 二叉搜索树迭代器

next() 和 hasNext() 操作的平均时间复杂度是 O(1),并使用 O(h) 内存,其中 h 是树的高度。可考虑用栈模拟中序遍历来做。栈最大是树的高度。

class BSTIterator {
     
public:
    stack<TreeNode*> stk;
    BSTIterator(TreeNode* root) {
     
    	//初始化
        while(root){
     
            stk.push(root);
            root = root->left;
        }
    }
    
    /** @return the next smallest number */
    int next() {
     
        auto p = stk.top(); stk.pop();
        int res = p->val;
        //对右子树中序遍历
        p = p->right;
        while(p){
     
            stk.push(p);
            p = p->left;
        }
        return res;
    }
    
    /** @return whether we have a next smallest number */
    bool hasNext() {
     
        return stk.size();
    }
};

10.acwing19. 二叉树的下一个节点

class Solution {
     
public:
    TreeNode* inorderSuccessor(TreeNode* p) {
     
        //如存在右子树,返回右子树的最左节点
        if(p->right) {
     
            p = p->right;
            //左孩子存在时,才向左遍历
            while(p->left) p = p->left;
            return p;
        }
        //如果存在父亲,且p是其父亲的右子树,p->father的右子树遍历完成。
        //以p->father的根节点的树遍历完成,继续向上寻找p->father的父亲
        while(p->father && p->father->right == p){
     
             p = p->father;
        }
        //当p是其父亲的左孩子,证明p->father的左树已经遍历完,此时遍历p->father
        if(p->father && p->father->left == p) return p->father;
        return NULL;
    }
};

你可能感兴趣的:(算法,二叉树,数据结构,dfs,leetcode)