Leetcode刷题之二叉排序树、平衡二叉搜索树1

文章目录

  • 知识回顾
  • 例题讲解
    • 1. 面试题04.06: 后继者
    • 2. Leetcode 450: 删除二叉搜索树中的节点
    • 3. Leetcode 1382: 将二叉搜索树变平衡

知识回顾

二叉排序树(二叉搜索树)的基础知识在之前的文章中有详细介绍,包括概念、插入、删除等基本操作,并进行了代码演示。
AVL树作为一种特殊的二叉排序树,对树高做了限制,在之前的文章中也有介绍,包括基本概念,性质,插入与删除过程中出现失衡后如何调整。并进行了代码演示。

例题讲解

1. 面试题04.06: 后继者

题目链接
题目解析:如果所求节点的左右子树都不为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:
    TreeNode *last_node; //遍历的上一个节点
    TreeNode* inorder(TreeNode *root, TreeNode *p) {
        if (root == nullptr) return nullptr;
        TreeNode *node;
        if (node = inorder(root->left, p)) return node;
        if (last_node == p) {
            return root;
        }
        last_node = root;
        if (node = inorder(root->right, p)) return node;
        return nullptr;

    }
    TreeNode* inorderSuccessor(TreeNode* root, TreeNode* p) {
        if (root == nullptr) return nullptr;
        return inorder(root, p);  //中序遍历
    }
};

总结:结构化遍历,注意if (node = inorder(root->left, p))是必要的,因为可能会在左子树中找到了目标节点,那直接返回之前的结果即可。

2. Leetcode 450: 删除二叉搜索树中的节点

题目链接
题目解析:参考之前介绍过的二叉搜索树基础知识中的代码演示,代码可直接复用。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    TreeNode *predecessor(TreeNode *root) {
        TreeNode *node = root->left;
        while (node->right) node = node->right;
        return node;
    }
    TreeNode* deleteNode(TreeNode* root, int key) {
        if (root == nullptr) return root;
        if (key < root->val) root->left = deleteNode(root->left, key);
        else if (key > root->val) root->right = deleteNode(root->right, key);
        else {
            if (root->left == nullptr || root->right == nullptr) {
                TreeNode *node = root->left == nullptr ? root->right : root->left;
                delete root;
                return node;
            }else {
                TreeNode *node = predecessor(root);
                root->val = node->val;
                root->left = deleteNode(root->left, node->val);
            }
        }
        return root;
    }
};

3. Leetcode 1382: 将二叉搜索树变平衡

题目链接
题目分析:一种做法是顺序遍历二叉搜索树,然后按照平衡二叉树的插入方法,结合各种左旋,右旋操作重新构造一颗平衡二叉树。
但是也可以换一个思路,将二叉搜索树看成一个从小到大排列的顺序结构,根节点取中间那个位置,左右子树分别取两边,递归的进行构建二叉树,最终一定是平衡的。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    void getNodes(TreeNode *root, vector<TreeNode *> &nodes) {
        if (root == nullptr) return;
        getNodes(root->left, nodes);
        nodes.push_back(root);
        getNodes(root->right, nodes);
    }
    TreeNode *build_tree(vector<TreeNode *> &nodes, int l, int r) {
        if (l > r) return nullptr;
        int mid = (l + r) >> 1;
        TreeNode *root = nodes[mid];
        root->left = build_tree(nodes, l, mid - 1);
        root->right = build_tree(nodes, mid + 1, r);
        return root;
    }
    TreeNode* balanceBST(TreeNode* root) {
        vector<TreeNode *> nodes;
        getNodes(root, nodes);  //将二叉树的节点从小到大才能到nodes中
        return build_tree(nodes, 0, nodes.size() - 1);  //根据顺序结构nodes构造一个平衡的二叉树
    }
};

总结:将二叉搜索树看成右小到大排列的顺序结构。

你可能感兴趣的:(算法,leetcode,算法,职场和发展,数据结构)