• wy的leetcode刷题记录_Day51


    wy的leetcode刷题记录_Day51

    声明

    本文章的所有题目信息都来源于leetcode
    如有侵权请联系我删掉!
    时间:2022-11-24

    前言

    795. 区间子数组个数

    今天的每日一题是:795. 区间子数组个数

    题目介绍

    给你一个整数数组 nums 和两个整数:left 及 right 。找出 nums 中连续、非空且其中最大元素在范围 [left, right] 内的子数组,并返回满足条件的子数组的个数。

    生成的测试用例保证结果符合 32-bit 整数范围。

    示例 1:
    输入:nums = [2,1,4,3], left = 2, right = 3
    输出:3
    解释:满足条件的三个子数组:[2], [2, 1], [3]

    示例 2:
    输入:nums = [2,9,2,5,6], left = 2, right = 8
    输出:7

    思路

    方法一:双指针法:首先我们将数组中的数分为三部分:1.小于left;2.大于等于left并且小于等于right;3.大于right这三种,为了满足题意我们的子数组必须满足不存在3的情况下至少有一个情况2。我们遍历整个数组以此时的位置为右边界,每当出现情况2时我们更新一个变量last_1,该变量表示上一个情况2出现的位置,每当出现情况3时我们更新一个变量last_2并且将last_1置为-1(因为在last_2左边的数都不满足条件了),该变量表示上一个情况3出现的位置。当没有情况2 出现的时候说明此时以i为右边界的情况中不存在满足条件的情况,继续拓展右边界。当有情况2,无情况3的时候,说明左边界可以在[0,i]中任选。当有情况2,有情况3的时候,说明我们只能在[last_1,last_2]之间选择左边界才能满足条件。
    方法二(来自题解):计数法:根据方法一的结论,我们求出子数组必须满足不存在3的情况下至少有一个情况2的个数。所以,我们可以先求出只包含 0 或 1 的子区间数目,再减去只包括 0 的子区间数目。我们使用了一个辅助函数用来计算数组 nums 中所有元素小于等于 lower 的子数组数目。

    代码

    双指针法:

    class Solution {
    public:
        int numSubarrayBoundedMax(vector<int>& nums, int left, int right) {
            int n=nums.size();
            int ans=0;
            for(int i=0;i<n;i++)
            {
                if(nums[i]<left)
                    nums[i]=0;
                else if(nums[i]>=left&&nums[i]<=right)
                    nums[i]=1;
                else if(nums[i]>right)
                    nums[i]=2;
            }
            int last_1=-1;
            int last_2=-1;
            for(int i=0;i<n;i++)
            {
                if(nums[i]==1)
                    last_1=i;
                else if(nums[i]==2)
                {
                    last_1=-1;
                    last_2=i;
                }
    
                if(last_1!=-1)
                    ans+=last_1-last_2;
            }
            return ans;
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    计数法:

    class Solution {
    public:
        int numSubarrayBoundedMax(vector<int>& nums, int left, int right) {
            return count(nums, right) - count(nums, left - 1);
        }
    
        int count(vector<int>& nums, int lower) {
            int res = 0, cur = 0;
            for (auto x : nums) {
                cur = x <= lower ? cur + 1 : 0;
                res += cur;
            }
            return res;
        }
    };
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    收获

    简单的模拟题,需要考虑一些情况,但没有特别复杂的情况

    98. 验证二叉搜索树

    98. 验证二叉搜索树

    题目介绍

    给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。

    有效 二叉搜索树定义如下:

    节点的左子树只包含 小于 当前节点的数。
    节点的右子树只包含 大于 当前节点的数。
    所有左子树和右子树自身必须也是二叉搜索树。

    示例 1:
    在这里插入图片描述
    输入:root = [2,1,3]
    输出:true

    示例 2:
    在这里插入图片描述
    输入:root = [5,1,4,null,null,3,6]
    输出:false
    解释:根节点的值是 5 ,但是右子节点的值是 4 。

    思路

    根据搜索树的性质,我们通过中序遍历的方法得到一个数组,这个数组在基于搜索树的性质上一定是一个严格升序数组,所以我们基于此判定即可,同理可写出递归和递推。

    代码

    递归:

    /**
     * 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:
        vector<int> arr;
        bool isValidBST(TreeNode* root) {
            travel(root);
            int n=arr.size();
            for(int i=1;i<n;i++)
            {
                if(arr[i]<=arr[i-1])
                    return false;
            }
            return true;
        }
        void travel(TreeNode* root)
        {
            if(root==nullptr)
                return;
            travel(root->left);
            arr.push_back(root->val);
            travel(root->right);
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    递推:

    class Solution {
    public:
        bool isValidBST(TreeNode* root) {
            stack<TreeNode*> stack;
            long long inorder = (long long)INT_MIN - 1;
    
            while (!stack.empty() || root != nullptr) {
                while (root != nullptr) {
                    stack.push(root);
                    root = root -> left;
                }
                root = stack.top();
                stack.pop();
                // 如果中序遍历得到的节点的值小于等于前一个 inorder,说明不是二叉搜索树
                if (root -> val <= inorder) {
                    return false;
                }
                inorder = root -> val;
                root = root -> right;
            }
            return true;
        }
    };
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    收获

    巩固了搜索树和中序遍历的知识

  • 相关阅读:
    使用css制作3D盒子,目的是把盒子并列制作成3D货架
    高压放大器在金属材料静电悬浮过程中的应用
    java单例模式
    基于Java+SpringBoot+Vue前后端分离智慧生活商城系统设计和实现
    RMI反序列化学习
    中国剩余定理
    项目结束需要经历的5个关键步骤
    网络适配器设置步骤
    推荐14个写Java代码的好习惯
    D1s芯片启动流程(BROM System)分析
  • 原文地址:https://blog.csdn.net/m0_54015435/article/details/128079168