【leetcode】数据结构—二叉树、二叉搜索树

二叉树

  • 101 对称二叉树
/**
 * 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) {
        return _isSymmetric(root, root);
    }

    bool _isSymmetric(TreeNode* rootA, TreeNode* rootB){
        if(rootA==nullptr and rootB==nullptr) return true;
        if(rootA==nullptr || rootB==nullptr) return false;
        if(rootA->val != rootB->val) return false;
        return _isSymmetric(rootA->left, rootB->right) && _isSymmetric(rootA->right, rootB->left);
    }
};
  • 二叉树的后序遍历
    用哈希集合存储访问过的点,并且以根节点、右节点、左节点的顺序入栈,当第二次访问到根节点或者当前节点为叶子节点,就把值存入结果之中。
class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> res;
        if(root == nullptr) return res;
        unordered_set<TreeNode*> hash;
        stack<TreeNode*> st;
        st.push(root);
        while(!st.empty()){
            TreeNode* tmp = st.top();
            st.pop();
            if(hash.count(tmp)){//已经访问过一次
                res.push_back(tmp->val);
            }
            else if(tmp->left==nullptr and tmp->right==nullptr) res.push_back(tmp->val);
            else{
                st.push(tmp);
                if(tmp->right) st.push(tmp->right);
                if(tmp->left) st.push(tmp->left);
                hash.insert(tmp);
            }
        }
        return res;
    }
};
  • 二叉树的最近公共祖先
class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if(root == p or root == q or root == nullptr) return root;
        TreeNode* left = lowestCommonAncestor(root->left, p, q);
        TreeNode* right = lowestCommonAncestor(root->right, p, q);
        if(left and right) return root;
        if(left and right==nullptr) return left;
        if(left == nullptr and right) return right;
        return nullptr;
    }
};

二叉搜索树

并不是左节点小于根节点,根节点小于右节点,而是要整个左子树的元素都应该小于根节点,整个右子树的元素都应该大于根节点,这就意味这在递归的过程中有上界和下界。

  • 98 验证二叉搜索树
class Solution {
public:
    bool isValidBST(TreeNode* root) {
        return _isvalid(root, nullptr, nullptr);
    }

    bool _isvalid(TreeNode* root, TreeNode* lower, TreeNode* upper){
        if(root == nullptr) return true;
        if(lower and lower->val >= root->val) return false;
        if(upper and upper->val <= root->val) return false;
        return _isvalid(root->left, lower, root) and _isvalid(root->right, root, upper); 
    }
};
  • 173 二叉搜索树迭代器
    直接的解法会想到中序遍历,用数组存储下就行。
class BSTIterator {
public:
    BSTIterator(TreeNode* root) {
        inorder(root);
    }
    
    /** @return the next smallest number */
    int next() {
        int tmp = q.front();
        q.pop();
        return tmp;
    }
    
    /** @return whether we have a next smallest number */
    bool hasNext() {
        return !q.empty();
    }

    void inorder(TreeNode* root){
        if(root == nullptr) return;
        if(root->left) inorder(root->left);
        q.push(root->val);
        if(root->right) inorder(root->right);
        return;
    }
private:
    queue<int> q;
};

但是上述算法的前提是得遍历一下树,时间复杂度和空间复杂度都随节点的个数增加,而提高效率的另一种方法就是可控制的递归,利用栈来模拟。

class BSTIterator {
public:
    BSTIterator(TreeNode* root) {
        step(root);
    }
    
    /** @return the next smallest number */
    int next() {
        int res;
        if(!q.empty()){
            TreeNode* tmp = q.top();
            q.pop();
            res = tmp->val;
            step(tmp->right);
        }
        return res;
    }
    
    /** @return whether we have a next smallest number */
    bool hasNext() {
        return !q.empty();
    }

    void step(TreeNode* root){
        while(root){
            q.push(root);
            root = root->left;
        }
    }
private:
    stack<TreeNode*> q;
};
  • 450 删除二叉搜索树中的节点
    删除操作比较复杂,主要有三种情况,1)叶子节点 2)有一个子节点 3)有两个子节点,其实2)和3)可以归并一下,因为都是找前驱节点和后继节点。
class Solution {
public:
    TreeNode* deleteNode(TreeNode* root, int key) {
        if(root == nullptr) return nullptr; //空节点
        if(root->val < key) root->right = deleteNode(root->right, key);
        else if(root->val > key) root->left = deleteNode(root->left, key);
        else{ //等于要删除的节点时有三种情况
            TreeNode* temp;
            if(root->left==nullptr and root->right==nullptr) root=nullptr; //叶子节点
            else if(root->left){ //只有左孩子,找前继,左孩子的右孩子
                temp = root->left;
                while(temp->right){
                    temp = temp->right;
                }
                root->val = temp->val;
                root->left = deleteNode(root->left, temp->val);
            }
            else{//只有右孩子,找后继,右孩子的左孩子
                temp = root->right;
                while(temp->left){
                    temp = temp->left;
                }
                root->val = temp->val;
                root->right = deleteNode(root->right, temp->val);
            }
        }
        return root;
    }
};

二叉搜索树可以用于有序地存储数据或者需要同时执行搜索、插入、删除等多步操作

发布了86 篇原创文章 · 获赞 10 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_36530992/article/details/104566162