2022-6-20 二叉搜索树的第k大节点,二叉搜索树中的插入操作,合法二叉搜索树,Range模块

1. 二叉搜索树的第k大节点

给定一棵二叉搜索树,请找出其中第 k 大的节点的值。

Example 1

输入: root = [3,1,4,null,2], k = 1
   3
  / \
 1   4
  \
   2
输出: 4

Example 2

输入: root = [5,3,6,2,4,null,null,1], k = 3
       5
      / \
     3   6
    / \
   2   4
  /
 1
输出: 4

Constraints:

  • 1 ≤ k ≤ 二叉搜索树元素个数

代码 [反中序遍历]

class Solution {
public:
    int kthLargest(TreeNode *root, int k) {
        stack<TreeNode *> st;
        TreeNode *cur = root;
        while (cur || !st.empty()) {
            if (cur) {
                st.push(cur);
                cur = cur->right;
            } else {
                cur = st.top();
                st.pop();
                if (--k == 0) return cur->val;
                cur = cur->left;
            }
        }
        return -1;
    }
};

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

给定二叉搜索树(BST)的根节点 root 和要插入树中的值 value ,将值插入二叉搜索树。 返回插入后二叉搜索树的根节点。 输入数据 保证 ,新值和原始二叉搜索树中的任意节点值都不同。

注意,可能存在多种有效的插入方式,只要树在插入后仍保持为二叉搜索树即可。 你可以返回 任意有效的结果

Example 1

输入:root = [4,2,7,1,3], val = 5
输出:[4,2,7,1,3,5]

Example 2

输入:root = [40,20,60,10,30,50,70], val = 25
输出:[40,20,60,10,30,50,70,null,null,25]

Constraints:

  • 树中的节点数将在 [0, 10^4]的范围内。
  • -10^8 <= Node.val <= 10^8
  • 所有值 Node.val独一无二 的。
  • -10^8 <= val <= 10^8
  • 保证 val 在原始BST中不存在。

代码

class Solution {
public:
    TreeNode *insertIntoBST(TreeNode *root, int val) {
        if (!root) return new TreeNode(val);
        TreeNode *node = root;
        while (node) {
            if (node->val < val) {
                if (!node->right) {
                    node->right = new TreeNode(val);
                    return root;
                }
                node = node->right;
            } else {
                if (!node->left) {
                    node->left = new TreeNode(val);
                    return root;
                }
                node = node->left;
            }
        }
        return root;
    }
};
class Solution {
public:
    TreeNode *insertIntoBST(TreeNode *root, int val) {
        if (!root) return new TreeNode(val);
        TreeNode *cur = root, *prev;
        while (cur) {
            prev = cur;
            cur = val < cur->val ? cur->left : cur->right;
        }
        val < prev->val ? prev->left = new TreeNode(val) : prev->right = new TreeNode(val);
        return root;
    }
};

3. 合法二叉搜索树

实现一个函数,检查一棵二叉树是否为二叉搜索树。

Example 1

输入:
    2
   / \
  1   3
输出: true

Example 2

输入:
    5
   / \
  1   4
     / \
    3   6
输出: false

代码

class Solution {
public:
    bool isValidBST(TreeNode* root) {
        stack<TreeNode*> st;
        auto cur=root;
        int prev=INT_MIN, flag=1;
        while(cur||!st.empty()){
            if(cur){
                st.push(cur);
                cur=cur->left;
            }else{
                cur=st.top();
                st.pop();
                if(cur->val<=prev&&flag==0) return false;
                prev=cur->val;
                flag=0;
                cur=cur->right;
            }
        }
        return true;
    }
};

4. Range 模块

A Range Module is a module that tracks ranges of numbers. Design a data structure to track the ranges represented as half-open intervals and query about them.

A half-open interval [left, right) denotes all the real numbers x where left <= x < right.

Implement the RangeModule class:

  • RangeModule() Initializes the object of the data structure.
  • void addRange(int left, int right) Adds the half-open interval [left, right), tracking every real number in that interval. Adding an interval that partially overlaps with currently tracked numbers should add any numbers in the interval [left, right) that are not already tracked.
  • boolean queryRange(int left, int right) Returns true if every real number in the interval [left, right) is currently being tracked, and false otherwise.
  • void removeRange(int left, int right) Stops tracking every real number currently being tracked in the half-open interval [left, right).

Example 1

Input
["RangeModule", "addRange", "removeRange", "queryRange", "queryRange", "queryRange"]
[[], [10, 20], [14, 16], [10, 14], [13, 15], [16, 17]]
Output
[null, null, null, true, false, true]

Explanation
RangeModule rangeModule = new RangeModule();
rangeModule.addRange(10, 20);
rangeModule.removeRange(14, 16);
rangeModule.queryRange(10, 14); // return True,(Every number in [10, 14) is being tracked)
rangeModule.queryRange(13, 15); // return False,(Numbers like 14, 14.03, 14.17 in [13, 15) are not being tracked)
rangeModule.queryRange(16, 17); // return True, (The number 16 in [16, 17) is still being tracked, despite the remove operation)

Constraints:

  • 1 <= left < right <= 10^9
  • At most 10^4 calls will be made to addRange, queryRange, and removeRange.

代码 [线段树]

属于是,模板拿来就用的题目。

struct SegNode {
    int l, r, sum, lazy;
    SegNode *left, *right;
    SegNode() {}
    SegNode(int l, int r) : l(l), r(r), sum(0), lazy(0), left(nullptr), right(nullptr) {}
};

class RangeModule {
public:
    SegNode *ST;

    //-------------- SegmentTree start ------------//

    SegNode *get_left(SegNode *rt) {
        if (rt->left == nullptr) {
            int mid = rt->l + ((rt->r - rt->l) >> 1);
            rt->left = new SegNode(rt->l, mid);
        }
        return rt->left;
    }

    SegNode *get_right(SegNode *rt) {
        if (rt->right == nullptr) {
            int mid = rt->l + ((rt->r - rt->l) >> 1);
            rt->right = new SegNode(mid + 1, rt->r);
        }
        return rt->right;
    }

    void push_up(SegNode *rt) { rt->sum = get_left(rt)->sum + get_right(rt)->sum; }

    void push_down(SegNode *rt) {
        if (rt->lazy != 0) {
            int v = rt->lazy;
            SegNode *ll = get_left(rt), *rr = get_right(rt);
            ll->lazy = v;
            rr->lazy = v;
            if (v == 1) {
                ll->sum = (ll->r - ll->l + 1);
                rr->sum = (rr->r - rr->l + 1);
            } else if (v == -1) {
                ll->sum = 0;
                rr->sum = 0;
            }
            rt->lazy = 0;
        }
    }

    void update(SegNode *rt, int ul, int ur, int val) {

        if (ul <= rt->l && rt->r <= ur) {
            rt->lazy = val;
            rt->sum = val == 1 ? rt->r - rt->l + 1 : 0;
            return;
        }
        int mid = rt->l + ((rt->r - rt->l) >> 1);
        SegNode *ll = get_left(rt), *rr = get_right(rt);
        push_down(rt);
        if (ur <= mid) {
            update(ll, ul, ur, val);
        } else if (mid + 1 <= ul) {
            update(rr, ul, ur, val);
        } else {
            update(ll, ul, ur, val);
            update(rr, ul, ur, val);
        }
        push_up(rt);
    }

    int query(SegNode *rt, int ql, int qr) {
        if (ql <= rt->l && rt->r <= qr) {
            return rt->sum;
        }
        int mid = (rt->l + rt->r) / 2;
        SegNode *ll = get_left(rt);
        SegNode *rr = get_right(rt);
        push_down(rt);
        if (qr <= mid) {
            return query(ll, ql, qr);
        } else if (mid + 1 <= ql) {
            return query(rr, ql, qr);
        }
        return query(ll, ql, qr) + query(rr, ql, qr);
    }

    //--------------- SegmentTree end -------------//

    RangeModule() { ST = new SegNode(0, (int) 1e9); }

    void addRange(int left, int right) { update(ST, left, right - 1, 1); }

    bool queryRange(int left, int right) { return query(ST, left, right - 1) == (right - left); }

    void removeRange(int left, int right) { update(ST, left, right - 1, -1); }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值