加载中...

二叉树 续 之前太多了

BST 搜索对应的值 ,因为是bst所以dfs不需要回溯,所以使用迭代一般都会很舒服!!

TreeNode* searchBST(TreeNode* root, int val) {
            if(!root) return nullptr;
            while(root){
                
                 if(root->val>val) root=root->left;
                
             else if(root->val<val) root=root->right;
            else return root;
            }return nullptr;
    }

检查是不是二叉搜索树(中序遍历最好用!!)

使用中序遍历将每个结点的值放进去数组 然后检查这个数组是不是满足升序遍历
vector<int> vec;
void traversal(TreeNode* root) {
    if (root == NULL) return;
    traversal(root->left);//遍历左边
    vec.push_back(root->val); // 将二叉搜索树转换为有序数组
    traversal(root->right);//遍历右边
}

public:TreeNode* pre=nullptr;//全局变量记录前一个
    bool isValidBST(TreeNode* root) {//
            if(!root) return true ;//
            bool left= isValidBST(root->left);//先左边
            if(pre&&pre->val>=root->val){return false;//注意是pre存在的时候,否则会被说成是
        }pre=root;//再中间
            bool right=isValidBST(root->right);//再右边
        return left&&right;
逆天的迭代前序遍历 用时0ms
bool isValidBST(TreeNode* root) {
        stack<TreeNode*> st;//
        TreeNode* cur = root;
        TreeNode* pre = NULL; // 记录前一个节点
        while (cur != NULL || !st.empty()) {
            if (cur != NULL) {//存入当前值,顺便往左
                st.push(cur);//如果左边有结点,就一直往左走 直到不能走 而且最左边的在最上层
                cur = cur->left;                // 左
            } else {//当cur为空,cur变成栈顶元素(左边),
                cur = st.top();                 // 中
                st.pop();//对左边的pop出去
                if (pre != NULL && cur->val <= pre->val)
                return false;//进行判断
                pre = cur; //pre保存当前一个访问的结点,释放cur 
                cur = cur->right;               // 右
      //顺便如果有右结点  继续往右走,            
        }
        }
        return true;

找二叉树中的众数元素

vector<int> res;
    map<int,int >ma;
    void dfs(TreeNode* node){
        if(!node) return;
        ma[node->val]++;
        dfs(node->left);
        dfs(node->right);
        
    }
    static bool cmp(pair<int,int >a,pair<int ,int >b){
        return a.second>b.second;
    }//static必须要有,使用pair,必须是static

    vector<int> findMode(TreeNode* root) {
        if(!root) return res;
        dfs(root);
    vector<pair<int,int> >v(ma.begin(),ma.end());//不能够对map的次值直接进行排序,先转话成pair的数组
    sort(v.begin(),v.end(),cmp );//再数组用sort排序,按照次值来排,要使用stacic
    res.push_back(v[0].first);
    for(int i=1;i<v.size();i++){
        if(v[0].second==v[i].second)//频率相等就加入
        res.push_back(v[i].first);
    }
    return res;     
    }

对于二叉搜索树直接中序遍历即可得到排好序的值

寻找公共祖先 92

class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if (root == q || root == p || root == NULL) return root;//该节点等于对应的值,直接返回该节点,此时的处理相当于最上层的被立刻返回,下层不在搜索,找到对应结点!!精彩
        
//以下都是对左右子树的处理了
TreeNode* left = lowestCommonAncestor(root->left, p, q);//左右中,后序遍历的过程,一直往左走
        TreeNode* right = lowestCommonAncestor(root->right, p, q);//返回值的逻辑 如果路径上不是p,q结点就会得到null结点的值(由于第一行)
    
        if (left && right) return root;
//两边都有值的情况,直接根结点 说明这个就是所求点祖先
        if (!left && right ) return right;
//只有一边有 说明有的那边就是所求的结点 ,一路向上返回即可
        else if (left && !right ) return left;//叶子结点的清理
        else  { //  (!left  && !right )
            return NULL;//左右两个null返回null
        }

    }
};

二叉搜索树中查祖先

TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {//找区间
        if (root->val > p->val && root->val > q->val) {
            return lowestCommonAncestor(root->left, p, q);//如果当前结点的值大于p,q两个结点的,说明答案在当前结点的左边
        } else if (root->val < p->val && root->val < q->val) {
            return lowestCommonAncestor(root->right, p, q);//小于p,q两个节点的值,说明答案在当前结点的右边
        } else return root;//如果在p,q区间之间,就说明 需要直接return
    }


非avl树的插入操作

TreeNode* insertIntoBST(TreeNode* root, int val) {
        if(!root) {//一直找到一个空结点,甚至包括了数据点为空树的情况
            TreeNode *p =new TreeNode(val);//为这个新节点设值即可
            return p;
        }
        if(root->val>val) root->left=insertIntoBST(root->left,val);//值大的话,在root->left那里寻找
        if(root->val<val) root->right=insertIntoBST(root->right,val);
        return root;//返回root
    }

上面迭代法

class Solution {
public:
    TreeNode* insertIntoBST(TreeNode* root, int val) {
        if (root == NULL) {
            TreeNode* node = new TreeNode(val);
            return node;
        }
        TreeNode* cur = root;
        TreeNode* parent = root; // 这个很重要,需要记录上一个节点,否则无法赋值新节点
        while (cur != NULL) {//一直直到空结点
            parent = cur;
            if (cur->val > val) cur = cur->left;
            else cur = cur->right;
        }
        TreeNode* node = new TreeNode(val);
        if (val < parent->val) parent->left = node;// 此时是用parent节点的进行赋值
        else parent->right = node;
        return root;
    }
};

bst中的删除

class Solution {
public:
    TreeNode* deleteNode(TreeNode* root, int key) {
        if (root == nullptr) return root; // 第一种情况:没找到删除的节点,遍历到空节点直接返回了
        if (root->val == key) {
            // 第二种情况:左右孩子都为空(叶子节点),直接删除节点, 返回NULL为根节点
            if (root->left == nullptr && root->right == nullptr) {
                ///! 内存释放
                delete root;
                return nullptr;
            }
            // 第三种情况:其左孩子为空,右孩子不为空,删除节点,右孩子补位 ,返回右孩子为根节点
            else if (root->left == nullptr) {
                auto retNode = root->right;
                ///! 内存释放
                delete root;
                return retNode;
            }
            // 第四种情况:其右孩子为空,左孩子不为空,删除节点,左孩子补位,返回左孩子为根节点
            else if (root->right == nullptr) {
                auto retNode = root->left;
                ///! 内存释放
                delete root;
                return retNode;
            }
            // 第五种情况:左右孩子节点都不为空,则将删除节点的左子树放到删除节点的右子树的最左面节点的左孩子的位置
            // 并返回删除节点右孩子为新的根节点。
            else {
                TreeNode* cur = root->right; // 找右子树最左面的节点
                while(cur->left != nullptr) {
                    cur = cur->left;
                }
                cur->left = root->left; // 把要删除的节点(root)左子树放在cur的左孩子的位置
                TreeNode* tmp = root;   // 把root节点保存一下,下面来删除
                root = root->right;     // 返回旧root的右孩子作为新root
                delete tmp;             // 释放节点内存(这里不写也可以,但C++最好手动释放一下吧)
                return root;
            }
        }
        if (root->val > key) root->left = deleteNode(root->left, key);
        if (root->val < key) root->right = deleteNode(root->right, key);
        return root;
    }
};

修剪二叉树

class Solution {
public:
    TreeNode* trimBST(TreeNode* root, int low, int high) {
        if (root == nullptr ) return nullptr;
        if (root->val < low) {
              // 寻找符合区间[low, high]的节点,如果当前值已经小于最小的区间,那么左边的值肯定更小,因此递归右边的值
            return trimBST(root->right, low, high);
        }
        if (root->val > high) {
             // 寻找符合区间[low, high]的节点,新建一个结点返回这个新建结点
            return trimBST(root->left, low, high);
        }
//对处于区间内的值,需要将则递归他的左右,这相当于重新建立一个树?
        root->left = trimBST(root->left, low, high); // root->left接入符合条件的左孩子
        root->right = trimBST(root->right, low, high); // root->right接入符合条件的右孩子
        return root;//返回这个根结点
    }
};

修剪二叉树

class Solution {
public:
    TreeNode* trimBST(TreeNode* root, int L, int R) {
        if (!root) return nullptr;

        // 处理头结点,让root移动到[L, R] 范围内,注意是左闭右闭
        while (root != nullptr && (root->val < L || root->val > R)) {
            if (root->val < L) root = root->right; // 小于L往右走
            else root = root->left; // 大于R往左走
        }
        TreeNode *cur = root;//使用cur修改
        // 此时root已经在[L, R] 范围内,处理左孩子元素小于L的情况
        while (cur != nullptr) {
            while (cur->left && cur->left->val < L) {
                cur->left = cur->left->right;
            }
            cur = cur->left;
        }
        cur = root;

        // 此时root已经在[L, R] 范围内,处理右孩子大于R的情况//先修改左边再修改右边
        while (cur != nullptr) {
            while (cur->right && cur->right->val > R) {
                cur->right = cur->right->left;
            }
            cur = cur->right;
        }
        return root;
    }
};

有序的数组转换为二叉搜索树

class Solution {
private:
    TreeNode* traversal(vector<int>& nums, int left, int right) {//二分法
        if (left > right) return nullptr;
        int mid = left + ((right - left) / 2);
        TreeNode* root = new TreeNode(nums[mid]);//每次只处理中点
        root->left = traversal(nums, left, mid - 1);
        root->right = traversal(nums, mid + 1, right);
        return root;
    }
public:
    TreeNode* sortedArrayToBST(vector<int>& nums) {
        TreeNode* root = traversal(nums, 0, nums.size() - 1);
        return root;
    }
};

变成累加树

class Solution {
private:
    int pre; // 记录前一个节点的数值
    void traversal(TreeNode* cur) { // 右中左遍历
        if (cur == NULL) return;
        traversal(cur->right);//右
        cur->val += pre;//中直接在树上进行修改,先从最右边的开始
        pre = cur->val;
        traversal(cur->left);//左
    }
public:
    TreeNode* convertBST(TreeNode* root) {
        pre = 0;
        traversal(root);
        return root;
    }
};
posted @ 2021-12-10 22:56  liang302  阅读(26)  评论(0编辑  收藏  举报