代码随想录第十一天|二叉树(4)

LeetCode 530. 二叉搜索树的最小绝对差

题目链接:LeetCode 530. 二叉搜索树的最小绝对差

思想:本题可以根据昨天的验证二叉搜索树的思路来,通过中序遍历得到一个升序的数组,然后笔案例这个升序数组,如果两个数之差小于目前记录的值的话,就更换一次。

代码如下:

    void bianli(TreeNode* cur, vector<int>& vec){
        if (!cur) return;
        bianli(cur->left, vec);
        vec.push_back(cur->val);
        bianli(cur->right, vec);
    }

    int getMinimumDifference(TreeNode* root) {
        vector<int> xulie;
        if (!root) return 0;
        bianli(root, xulie);
        int min = INT_MAX;
        for (int i = 1; i < xulie.size(); i++){
            if (abs(xulie[i] - xulie[i - 1]) <= min){
                min = abs(xulie[i] - xulie[i - 1]);
            }
        }
        return min;
    }

LeetCode 501. 二叉搜索树中的众数

题目链接:LeetCode 501. 二叉搜索树中的众数

思想:本题首先需要一个数组来接收众数,其次就是根据二叉搜索树的性质,采用中序遍历。其次就需要两个节点指针,一个是父亲节点,一个是当前节点,用于判断前后值是否一样。如果一样的话,就让记录众数频次的值+1;如果不一样,就让记录众数频次的值等于1;如果前一个节点是NULL的话,证明是树的根节点,记录众数频次值等于1。同时,记录一个最大众数频次,如果当前众数频次等于最大众数频次的话,将当前节点的值压入众数数组;如果当前众数频次大于最大众数频次的话,更新最大众数频次,并将众数数组元素清空,把当前节点数值压入众数数组。

代码如下:

    int count = 0;
    int maxCount = 0;
    TreeNode* pre = NULL;
    vector<int> mode;
    void bianli(TreeNode* cur){
        if (!cur) return;
        bianli(cur->left);
        if (pre == NULL) count = 1;
        else if (pre->val == cur->val) count++;
        else count = 1;
        pre = cur;
        if (count == maxCount){
            mode.push_back(cur->val);
        } else if (count > maxCount){
            maxCount = count;
            mode.clear();
            mode.push_back(cur->val);
        }
        bianli(cur->right);
    }

    vector<int> findMode(TreeNode* root) {
        count = 0;
        maxCount = 0;
        mode.clear();
        bianli(root);
        return mode;
    }

LeetCode 236. 二叉树的最近公共祖先

题目链接:LeetCode 236. 二叉树的最近公共祖先

思想:本题需要先去确定终止条件,即如果当前节点是要找的p或者q节点或当前节点为空,就返回当前节点。然后去遍历整个数的节点,如果左右子树的返回结果都存在,就返回当前节点;如果子树返回节点为空,右子树不为空,就返回右子树;反之返回左子树。

代码如下:

    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if (root == p || root == q || !root) return root;
        TreeNode* left = lowestCommonAncestor(root->left, p, q);
        TreeNode* right = lowestCommonAncestor(root->right, p, q);
        if (left && right) return root;
        if (!left && right) return right;
        else if (left && !right) return left;
        else return NULL;
    }

LeetCode 235. 二叉搜索树的最近公共祖先

题目链接:LeetCode 235. 二叉搜索树的最近公共祖先

思想:本题就可以基于上题来优化,如果当前节点的值小于p 大于q 或者 小于q 大于p,就继续遍历左右子树;如果当前节点的值大于节点p q,就遍历左子树;如果当前节点的值小于节点p q,就遍历右子树。

代码如下:

    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if (root == p || root == q || root == NULL) return root;
        TreeNode* left = NULL;
        TreeNode* right = NULL;
        if (p->val < root->val < q->val || q->val < root->val < p->val) {
            left = lowestCommonAncestor(root->left, p, q);
            right = lowestCommonAncestor(root->right, p, q);
        } else if (root->val > p->val && root->val > q->val) {
            left = lowestCommonAncestor(root->left, p, q);
        } else {
            right = lowestCommonAncestor(root->right, p, q);
        }

        if (left && right) return root;
        else if (!left && right) return right;
        else if (left && !right) return left;
        else return NULL;
    }

LeetCode 701. 二叉搜索树中的插入操作

题目链接:LeetCode 701. 二叉搜索树中的插入操作

思想:本题其实很简单,就遍历二叉搜索树,遇到空节点就插入。怎么保证就是正确插入呢,即插入之后还是二叉搜索树。即遇到当前节点值大于val 时候就遍历左节点;反之遍历右节点即可。

代码如下:

    TreeNode* pre;
    void bianli(TreeNode* cur, int val){
        if (!cur) {
            TreeNode* node = new TreeNode(val);
            if (val < pre->val) pre->left = node;
            else if (val > pre->val) pre->right = node;
            return;
        }
        pre = cur;
        if (cur->val < val) bianli(cur->right, val);
        if (cur->val > val) bianli(cur->left, val);
        
    }
    TreeNode* insertIntoBST(TreeNode* root, int val) {
        pre = new TreeNode(0);
        if (!root) {
            pre->val = val; 
            return pre;
        }
        bianli(root, val);
        return root;
    }

LeetCode 450. 删除二叉搜索树中的节点

题目链接:LeetCode 450. 删除二叉搜索树中的节点

思想:本题比插入复杂,因为删除涉及到一个问题,即二叉搜索树的结构改变。所以遇到删除的节点有以下几种情况:

  1. 当前节点没有左右孩子,直接删去即可
  2. 当前节点有左孩子,没有右孩子,将当前节点用节点的左孩子代替
  3. 当前节点没有左孩子,有右孩子,将当前节点用节点的右孩子代替
  4. 当前节点既有左孩子又有右孩子,将左孩子放进右子树的最左面的节点下面,删除当前节点即可

代码如下:

    TreeNode* deleteNode(TreeNode* root, int key) {
        if (!root) return NULL;
        if (root->val == key && !root->left && !root->right){
            delete root;
            return NULL;
        } else if (root->val == key && !root->left && root->right){
            auto retNode = root->right;
            delete root;
            return retNode;
        } else if (root->val == key && root->left && !root->right){
            auto retNode = root->left;
            delete root;
            return retNode;
        } else if (root->val == key && root->left && root->right){
            TreeNode* cur = root->right;
            while (cur->left != nullptr){
                cur = cur->left;
            }
            cur->left = root->left;
            TreeNode* temp = root;
            root = root->right;
            delete temp;
            return root;
        }
        if (root->val > key) root->left = deleteNode(root->left, key);
        if (root->val < key) root->right = deleteNode(root->right, key);
        return root;
    }

总结

这几天学习到了一个新的知识点,就是遍历二叉树的方式。

bianli(cur->left);
bianli(cur->right);

这种遍历方式一般用于遍历二叉树的边。

cur->left = bianli(cur->left);
cur->right = bianli(cur->right);

这种遍历方式一般用于遍历整个二叉树。

主要情况分为以下几种:

  • 如果需要搜索整棵二叉树且不用处理递归返回值,递归函数就不要返回值。
  • 如果需要搜索整棵二叉树且需要处理递归返回值,递归函数就需要返回值。
  • 如果要搜索其中一条符合条件的路径,那么递归一定需要返回值,因为遇到符合条件的路径了就要及时返回。
  • 17
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值