【算法】【树】树相关问题总结

树的递归

104. 二叉树的最大深度

题目链接:https://leetcode-cn.com/problems/maximum-depth-of-binary-tree/

递归

利用递归,我们可以很方便地求得最大深度。当前树的最大深度是左右子树的最大深度加1。时间复杂度为O(n),树的每个节点都要遍历一次。

int maxDepth(TreeNode* root) {
return  root?  1  +  max(maxDepth(root->left),  maxDepth(root->right)):  0;
}

迭代

利用队列来模拟

/**
 * 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 maxDepth(TreeNode* root) {
        if(!root) return 0;
        queue<TreeNode *> q;
        q.push(root);
        int res = 0;
        while(!q.empty())
        {
            //n表示当前层有多少元素
            int n = q.size();
            while(n--)
            {
                //遍历当前层的所有元素,并把其左右节点压入队列中
                TreeNode* tmp = q.front();
                q.pop();
                if(tmp -> left) q.push(tmp -> left);
                if(tmp -> right) q.push(tmp -> right);
            }
            //一层+1
            res++;
        }
        return res;
    }
};

101. 对称二叉树

题目链接:https://leetcode-cn.com/problems/symmetric-tree/

递归

两个子树互为镜像当且仅当:

  1. 两个子树的根节点相等;
  2. 第一颗子树的左子树和第二颗子树的右子树互为镜像,且第一颗子树的右子树与第二颗子树的左子树互为镜像;

时间复杂度: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:
    bool isSymmetric(TreeNode* root) {
        //根节点为空,为true
        bool res = true;
        if(root) res = isSym(root -> left, root -> right);
        return res; 
    }
    bool isSym(TreeNode* l, TreeNode* r)
    {
        //如果左右节点同时为空,则说明对称
        if(!l && !r) return true;
        //如果左右节点其中一个为空,则不是对称的
        if(!l || !r) return false;
        //如果做左节点的值不等于右节点的值,也不是对称的
        if(l -> val != r -> val) return false;
        //递归判断第一颗子树的左子树和第二颗子树的右子树
        //       第一颗子树的右子树和第二颗子树的左子树
        //.是否对称
        return isSym(l -> left, r -> right) && isSym(l -> right, r -> 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;
        queue<TreeNode*> q;
        //先将左右子树依次入队
        q.push(root -> left);
        q.push(root -> right);
        while(!q.empty())
        {
            //从队列中取出两个节点,进行比较
            //左节点
            TreeNode* l = q.front();
            q.pop();
            //右节点
            TreeNode* r = q.front();
            q.pop();
            
            //都为空,继续往后判断
            if(!l && !r) continue;
            //其中一个为空,不对称
            if(!l || !r) return false;
            //二者值不相同,不对称
            if(l -> val != r -> val) return false;

            //第一颗树的左孩子与第二颗树的右孩子应该相同
            //第一颗树的左孩子入队
            q.push(l -> left);
            //第二颗树的右孩子入队
            q.push(r -> right);
            //第一颗树的右孩子与第二颗树的左孩子应该相同
            //第一颗树的右孩子入队
            q.push(l -> right);
            //第一颗树的左孩子入队
            q.push(r -> left);
        }
        return true;
    }
};

110. 平衡二叉树

题目链接:https://leetcode-cn.com/problems/balanced-binary-tree/

递归

根据平衡二叉树的定义:一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过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:
    bool isBalanced(TreeNode* root) {
    	//根节点为空,平衡
        if(!root) return true;
        return abs(length(root -> left) - length(root -> right)) <= 1 && isBalanced(root -> left) && isBalanced(root -> right);
    }
    int length(TreeNode* root)
    {
        return root ? 1 + max(length(root -> left), length(root -> right)) : 0;
    }
};

543. 二叉树的直径

题目链接:https://leetcode-cn.com/problems/diameter-of-binary-tree/

递归

路径的长度为节点数目减1,使用深度优先搜索,遍历二叉树,每次更新ans为max(ans, l + r + 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:
    int ans = 1;
    int diameterOfBinaryTree(TreeNode* root) {
        dfs(root);
        return ans - 1;
    }
    int dfs(TreeNode* root)
    {
        //空结点返回0
        if(!root) return 0;
        //左儿子为根的子树的深度
        int l = dfs(root -> left);
        //右儿子为根的子树的深度
        int r = dfs(root -> right);
        //更新ans
        ans = max(ans, l + r + 1);
        return max(l, r) + 1;
    }
};

437. 路径总和Ⅲ

题目链接:https://leetcode-cn.com/problems/path-sum-iii/

递归

/**
 * 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 pathSum(TreeNode* root, int sum) {
        if (!root) return 0;
        return dfs(root, sum) + pathSum(root->left, sum) + pathSum(root->right, sum);
    }
    int dfs(TreeNode* root, int sum)
    {
        if (nullptr == root) return 0;
        sum -= root->val;
        return (0 == sum ? 1 : 0) + dfs(root->left, sum) + dfs(root->right, sum);
    }
};

非递归

class Solution 
{
public:
    int helper(TreeNode* root, int sum, vector<int>& path) 
    {
        if (!root) return 0;
        path.push_back(root->val);
        int sum_cur = 0;
        int res = 0;
        for (int i= path.size()-1; i>=0; i--) 
        {
            sum_cur+= path[i];
            if (sum_cur == sum) ++res;
        }
        res += helper(root->left, sum, path) + helper(root->right, sum, path);
        path.pop_back();
        return res;
    }
    int pathSum(TreeNode* root, int sum) 
    {
        vector<int> path;
        return helper(root, sum, path);
    }
};

34. 二叉树中和为某一值的路径(剑指offer)

题目链接:https://leetcode-cn.com/problems/er-cha-shu-zhong-he-wei-mou-yi-zhi-de-lu-jing-lcof/

递归

使用深度优先搜索来完成,

/**
 * 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> path;
    vector<vector<int>> res;
    vector<vector<int>> pathSum(TreeNode* root, int sum) {
        dfs(root, sum);
        return res;
    }
    void dfs(TreeNode* root, int sum)
    {
        if(!root) return ;
        path.push_back(root->val);
        sum -= root -> val;
        //判断当前节点是不是叶子节点,并且是否满足sum=0
        if(!root -> left && !root -> right && !sum) res.push_back(path);
        //递归处理左右子树
        dfs(root -> left, sum);
        dfs(root -> right, sum);
        //path还原
        path.pop_back();
    }
};

26. 树的子结构(剑指offer)

题目链接:https://leetcode-cn.com/problems/shu-de-zi-jie-gou-lcof/

递归

从根节点开始递归判断B是不是A的子树

  1. 如果A或B为空,返回false;

  2. 如果以A当前节点为根节点的子树与B中节点均相同,返回true;

  3. 判断以A当前节点的左右节点的子树与B中节点均相同,有一个相同则为ture;

    其中用到isSame函数判断两颗树的节点是否相同,递归进行判断:

    ​ B为空,表示遍历结束,满足条件,返回true

    ​ A节点为空或者A节点的值不等于B节点的值,返回false;

    ​ 判断A的左子树与B的左子树,A的右子树与B的右子树是否相等

    /**
     * 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 isSubStructure(TreeNode* A, TreeNode* B) {
            if(!A || !B) return false;
            if(isSame(A, B)) return true;
            return isSubStructure(A -> left, B) || isSubStructure(A -> right, B);
        }
        bool isSame(TreeNode *A ,TreeNode *B)
        {
            if(!B) return true;
            if(!A || A -> val != B -> val) return false;
            return isSame(A -> left, B->left) && isSame(A -> right, B -> right);
        }
    };
    

27. 二叉树的镜像(剑指offer)

题目链接:https://leetcode-cn.com/problems/er-cha-shu-de-jing-xiang-lcof/

队列

将根节点入队,从根节点开始,如果当前节点不空,交换当前节点的左右节点,并将左右节点依次入队;直到队列为空;

/**
 * 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* mirrorTree(TreeNode* root) {
        queue<TreeNode*> q;
        q.push(root);
        while (!q.empty()) {
            TreeNode* node = q.front();
            q.pop();
            if (node == NULL) {
                continue;
            }
            //交换两个左右节点
            swap(node->left, node->right);
            q.push(node->left);
            q.push(node->right);
        }
        return root;
    }
};

前中后序遍历

144. 前序遍历

题目链接:https://leetcode-cn.com/problems/binary-tree-preorder-traversal/

迭代实现:递归实质就是栈实现的,可以用栈来迭代模拟。注意入栈顺序

/**
 * 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> preorderTraversal(TreeNode* root) {
        vector<int> res;
        //空树
        if(!root) return res;
        stack<TreeNode*> st;
        //根节点入栈
        st.push(root);
        while(!st.empty())
        {
            auto node = st.top();
            
            res.push_back(node -> val);
            st.pop();
            //右
            if(node -> right) st.push(node -> right);
            //左
            if(node -> left) st.push(node -> left);
        }
        return res;
    }
};

145. 后序遍历

题目链接:https://leetcode-cn.com/problems/binary-tree-postorder-traversal/

指针

/**
 * 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> postorderTraversal(TreeNode* root) {
        vector<int> res;
        TreeNode *dummy = new TreeNode(-1);
        dummy->left = root;
        root = dummy;
        while (root)
        {
            if (!root->left) root = root->right;
            else
            {
                TreeNode *pre = root->left;
                while (pre->right && pre->right != root) pre = pre->right;
                if (pre->right)
                {
                    pre->right = 0;
                    int top = res.size();
                    for (TreeNode *p = root->left; p; p = p->right)
                        res.push_back(p->val);
                    reverse(res.begin() + top, res.end());
                    root = root->right;
                }
                else
                {
                    pre->right = root;
                    root = root->left;
                }
            }
        }
        return res;
    }
};

队列

/**
 * 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> postorderTraversal(TreeNode* root) {
        deque<TreeNode*> d;
        vector<int> res;
        if(!root) return res;
        d.push_front(root);
        while(!d.empty())
        {
            TreeNode* cur = d.front();
            res.push_back(cur -> val);
            if(cur -> left) d.push_front(cur -> left);
            if(cur -> right) d.push_front(cur -> right);
        }
        return res;

    }
};

class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) 
    {
        vector<int> res;
        stack<TreeNode*> st;
        if(root!=nullptr) st.push(root);
        while(!st.empty())
        {
            TreeNode *t = st.top();
            st.pop();
            if(t!=nullptr)
            {
                st.push(t);  //在右节点之前重新插入该节点,以便在最后处理(访问值)
                st.push(nullptr); //nullptr跟随t插入,标识已经访问过,还没有被处理
                if(t->right) st.push(t->right);
                if(t->left) st.push(t->left);
            }else
            {
                res.push_back(st.top()->val);
                st.pop();
            }
        }
        return res;   
    }
};

94. 中序遍历

题目链接:https://leetcode-cn.com/problems/binary-tree-inorder-traversal/

class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> res;
        stack<TreeNode*> st;
        if(root != nullptr) st.push(root);
        while(!st.empty())
        {
            TreeNode *t = st.top();
            st.pop();
            if(t != nullptr)
            {
                if(t -> right) st.push(t -> right);
                st.push(t);  //在左节点之前重新插入该节点,以便在左节点之后处理(访问值)
                st.push(nullptr); //nullptr跟随t插入,标识已经访问过,还没有被处理
                if(t -> left) st.push(t -> left);
            }else
            {
                res.push_back(st.top() -> val);
                st.pop();
            }
        }
        return res;
    }
};

07. 重建二叉树(剑指offer)

题目链接:https://leetcode-cn.com/problems/zhong-jian-er-cha-shu-lcof/

递归建立整棵二叉树:先递归创建左右子树,然后创建根节点,并让指针指向两棵子树。

  1. 先利用前序遍历找根节点:前序遍历的第一个数,就是根节点的值;
  2. 在中序遍历中找到根节点的位置 k,则 k 左边是左子树的中序遍历,右边是右子树的中序遍历;
    假设左子树的中序遍历的长度是 ll,则在前序遍历中,根节点后面的 ll 个数,是左子树的前序遍历,剩下的数是右子树的前序遍历;
  3. 有了左右子树的前序遍历和中序遍历,我们可以先递归创建出左右子树,然后再创建根节点;
  4. 时间复杂度分析:我们在初始化时,用哈希表(unordered_map<int,int>)记录每个值在中序遍历中的位置,这样我们在递归到每个节点时,在中序遍历中查找根节点位置的操作,只需要 O(1)的时间。此时,创建每个节点需要的时间是 O(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:
    
    unordered_map<int, int> pos;
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        int n = preorder.size();
        //用哈希表(unordered_map<int,int>)记录每个值在中序遍历中的位置
        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>& inor, int pl, int pr, int il, int ir)
    {
        if(pl > pr) return nullptr;
        //在中序遍历中找到根节点的位置 k
        int k = pos[pre[pl]] - il;
        TreeNode* root = new TreeNode(pre[pl]);
        root -> left = dfs(pre, inor, pl + 1, pl + k, il, il + k - 1);
        root -> right = dfs(pre, inor, pl + k + 1, pr, il + k + 1, ir);
        return root;
    }
};

37. 序列化二叉树(剑指offer)

递归

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Codec {
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 += "n ";
            return ;
        }
        res += to_string(root -> val) + ' ';
        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(u, data);
    }

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

// Your Codec object will be instantiated and called as such:
// Codec codec;
// codec.deserialize(codec.serialize(root));

层次遍历

102. 二叉树的层序遍历

题目链接:https://leetcode-cn.com/problems/binary-tree-level-order-traversal/submissions/

/**
 * 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>> levelOrder(TreeNode* root) {
        vector<vector<int>> res;
        if(!root) return res;
        queue<TreeNode*> q;
        q.push(root);
        while(!q.empty())
        {
            //下一层的节点数目
            int n = q.size();
            vector<int> v;
            for(int i = 0; i < n; i++)
            {
                auto node = q.front();
                q.pop();
                v.push_back(node -> val);
                //将下一层的节点依次入队
                if(node -> left) q.push(node -> left);
                if(node -> right) q.push(node -> right);
            }
            res.push_back(v);
        }
        return res;
    }
};

32-I. 从上到下打印二叉树(剑指offer)

题目链接:https://leetcode-cn.com/problems/cong-shang-dao-xia-da-yin-er-cha-shu-lcof/

/**
 * 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> levelOrder(TreeNode* root) {
        vector<int> res;
        if(!root) return res;
        queue<TreeNode*> q;
        q.push(root);
        while(!q.empty())
        {
            TreeNode* tmp = q.front();
            q.pop();
            res.push_back(tmp->val);
            if(tmp->left)
                q.push(tmp->left);
            if(tmp->right)
                q.push(tmp->right);
        }
        return res;
    }
};

32-II. 从上到下打印二叉树(剑指offer)

题目链接:https://leetcode-cn.com/problems/cong-shang-dao-xia-da-yin-er-cha-shu-ii-lcof/

/**
 * 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>> levelOrder(TreeNode* root) {
        vector<vector<int>> res;
        if(!root) return res;
        queue<TreeNode*> q;
        q.push(root);
        while(!q.empty())
        {
            vector<int> v;
            int len = q.size();
            while(len--)
            {
                TreeNode* tmp = q.front();
                v.push_back(tmp->val);
                q.pop();
                if(tmp->left) q.push(tmp->left);
                if(tmp->right) q.push(tmp->right);  
            }
            res.push_back(v);
        }
        return res;
    }
};

32-III. 从上到下打印二叉树(剑指offer)

题目链接:https://leetcode-cn.com/problems/cong-shang-dao-xia-da-yin-er-cha-shu-iii-lcof/

/**
 * 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>> levelOrder(TreeNode* root) {
        vector<vector<int>> res;
        if(!root) return res;
        deque<TreeNode*> q;
        q.push_back(root);
        int flag = 1;
        while(!q.empty())
        {
            vector<int> v;
            int len = q.size();

            while(len--)
            {
                TreeNode* tmp;
                if(flag == 1) 
                {
                    tmp = q.front();
                    q.pop_front();
                    v.push_back(tmp->val);
                    //顺序不能颠倒
                    if(tmp->left) q.push_back(tmp->left);
                    if(tmp->right) q.push_back(tmp->right);  
                }else
                {
                    tmp = q.back();
                    q.pop_back();
                    
                    if(tmp->right) q.push_back(tmp->right);  
                    if(tmp->left) q.push_back(tmp->left);
                }
                
            }
            flag = -flag;
            res.push_back(v);
        }
        return res;
    }
};

二叉搜索树BST

每个父节点,左节点的值小于父节点的值,右节点的值大于父节点的值;BST可以在O(nlogn)的时间内查找一个值是否存在:从根节点开始,若当前节点的值大于查找值则向左下走,若当前节点的值小于查找值则向右下走。同时因为二叉查找树是有序的,对其中序遍历的结果即为排好序的数组。

template <class T>
class BST 
{
struct Node 
{
	T data;
	Node* left;
	Node* right;
};
Node* root;
Node* makeEmpty(Node* t) 
{
	if (t == NULL) return NULL;
	makeEmpty(t->left);
	makeEmpty(t->right);
	delete t;
	return NULL;
}
Node* insert(Node* t, T x) 
{
	if (t == NULL)
    {
		t = new Node;
		t->data = x;
		t->left = t->right = NULL;
	} 
	else if (x < t->data)
    {
		t->left = insert(t->left, x);
	} 
	else if (x > t->data) 
	{
		t->right = insert(t->right, x);
	}
	return t;
}
Node* find(Node* t, T x)
{
	if (t == NULL) return NULL;
	if (x < t->data) return find(t->left, x);
	if (x > t->data) return find(t->right, x);
	return t;
}
Node* findMin(Node* t) 
{
	if (t == NULL || t->left == NULL) return t;
	return findMin(t->left);
}
Node* findMax(Node* t) 
{
	if (t == NULL || t->right == NULL) return t;
	return findMax(t->right);
}
Node* remove(Node* t, T x)
{
	Node* temp;
	if (t == NULL) return NULL;
	else if (x < t->data) t->left = remove(t->left, x);
	else if (x > t->data) t->right = remove(t->right, x);
	else if (t->left && t->right) 
	{
		temp = findMin(t->right);
		t->data = temp->data;
		t->right = remove(t->right, t->data);
	} 
	else
    {
		temp = t;
		if (t->left == NULL) t = t->right;
		else if (t->right == NULL) t = t->left;
		delete temp;
	}
	return t;
}
public:
	BST(): root(NULL) {}
	~BST() 
	{
		root = makeEmpty(root);
	}
	void insert(T x)
    {
		insert(root, x);
	}
	void remove(T x) 
	{
		remove(root, x);
	}
};

669. 修剪二叉搜索树

题目链接:https://leetcode-cn.com/problems/trim-a-binary-search-tree/

利用二叉查找树的大小关系,我们可以很容易地利用递归进行树的处理
1.如果大于R,则右枝都大于R,直接丢掉,递归左节点并返回;
2.如果小于L,则左枝都小于L,直接丢掉,递归右节点并返回;
3.否则分别递归处理左右节点,并返回当前节点。

时间复杂度:O(n) 空间复杂度: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:
    TreeNode* trimBST(TreeNode* root, int L, int R) 
    {
        if(!root) return root;
        //如果根节点的值大于R, 丢弃整个左子树
        if(root -> val > R) return trimBST(root -> left, L, R);
        //如果根节点的值小于L, 丢弃整个右子树
        if(root -> val < L) return trimBST(root -> right, L, R);
        //如果根节点在区间内,递归处理左右节点
        root -> left = trimBST(root -> left, L, R);
        root -> right = trimBST(root -> right, L, R);
        return root;
    }
};

54. 二叉搜索树的第k个节点(剑指offer)

题目链接:https://leetcode-cn.com/problems/er-cha-sou-suo-shu-de-di-kda-jie-dian-lcof/

/**
 * 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 kthLargest(TreeNode* root, int k) {
        stack<TreeNode *> st;
        int i = 0;
        while(!st.empty() || root)
        {
            while(root)
            {
                st.push(root);
                root = root -> right;
            }
            root = st.top();
            st.pop(); 
            i++ ;
            if(i == k) return root->val;
            root = root->left;
        }
        return 0;
    }
};

36. 二叉搜索树与双向链表(剑指offer)

题目链接:https://leetcode-cn.com/problems/er-cha-sou-suo-shu-yu-shuang-xiang-lian-biao-lcof/submissions/

/*
// Definition for a Node.
class Node {
public:
    int val;
    Node* left;
    Node* right;

    Node() {}

    Node(int _val) {
        val = _val;
        left = NULL;
        right = NULL;
    }

    Node(int _val, Node* _left, Node* _right) {
        val = _val;
        left = _left;
        right = _right;
    }
};
*/
class Solution {
public:
    Node* treeToDoublyList(Node* root) {
        root = treeToDoublyList(root, 0);
        
        if(!root) return NULL;
        Node* p = root;
        while(p -> right) p = p -> right;
        p -> right = root;
        root -> left = p;
        return root;
    }
    Node* treeToDoublyList(Node *root, int flag)
    {
        if(root == NULL) return NULL;
        Node *left_ = treeToDoublyList(root -> left, 1);
        Node *right_ = treeToDoublyList(root -> right, 0);

        root -> left = left_;
        root -> right = right_;

        if(left_) left_ -> right = root;
        if(right_) right_ -> left = root;
        Node *p = root;
        if(!flag) while(p -> left) p = p -> left;
        else while(p -> right) p = p -> right;
        return p;
    }

};

68-I 二叉搜索树的最近公共祖先(剑指offer)

题目链接:https://leetcode-cn.com/problems/er-cha-sou-suo-shu-de-zui-jin-gong-gong-zu-xian-lcof/

/**
 * 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* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if(!root) return nullptr;
        while(root)
        {
            if(p -> val < root -> val && q -> val < root -> val) root = root -> left;
            else if(p -> val > root -> val && q -> val > root -> val) root = root -> right;
            else break;
        }
        return root;
    }
};

68-II 二叉搜索树的最近公共祖先(剑指offer)

/**
 * 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* 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;
        return left ? left : right; // 只有一个非空则返回该指针,两个都为空则返回空指针
    }
};

33. 二叉搜索树的后续遍历序列(剑指offer)

题目链接:https://leetcode-cn.com/problems/er-cha-sou-suo-shu-de-hou-xu-bian-li-xu-lie-lcof/

class Solution {
public:
    vector<int> seq;
    bool verifyPostorder(vector<int>& postorder) {
        seq = postorder;
        return dfs(0, seq.size() - 1);
    }
    bool 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);
    }
};

猜你喜欢

转载自www.cnblogs.com/Trevo/p/12901895.html