• 【LeetCode】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 <= nums.length <= 105
    0 <= nums[i] <= 109
    0 <= left <= right <= 109

    方法:一次遍历

    class Solution {
    public:
        int numSubarrayBoundedMax(vector<int>& nums, int left, int right) {
            int last1 = -1, last2 = -1;
            int res = 0;
            for(int i=0; i<nums.size(); i++){
                if(nums[i] >= left && nums[i] <= right){
                    last1 = i;
                }
                else if(nums[i] > right){
                    last2 = i;
                    last1 = -1;
                }
                if(last1 != -1){
                    res += last1 - last2;
                }
            }
    
            return res;
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    心得

    • 这道题我一开始想用动态规划, dp[i][j] 表示 下标从 i 到 j 的数组是否满足条件,满足则为1,然而求解不出来。

    • 最终还是用了逐个遍历的方法:

      • 如果当前遍历的元素在 [left, right] 区间内,则可以循环遍历到出现 >right 的元素为止;
      • 如果当前遍历的元素
      • 如果当前遍历的元素 >right,则该元素作为分割点,直接考虑下一个元素。

      因此我的方法是不可行的,接下来介绍两种方法。

    方法:一次遍历

    • 思路:
    1. 一个子数组的范围落在区间 [left, right] 表示数组中不能出现大于 right 的元素,且至少包含一个在区间内的元素。
      我们将元素分为三类:

      • 小于 left,用 0 表示;
      • 落在区间 [left, right] 内,用 1 表示;
      • 大于 right,用 2 表示。

      因此,子数组中不能含有 2 ,且至少包含一个 1 。

    2. 我们依次遍历元素,将子数组区间的右端点固定为 i,求解有多少合法的子区间。过程中需要维护两个变量:

      • last1,表示上一次 1 出现的位置,默认为 -1;
      • last2,表示上一次 2 出现的位置,默认为 -1;

      如果last1不为-1,那么子数组以 last1为右边界点,合法的左边界点可以落在 (last2, last1) 之间。这样的左边界点有 last1 - last2 个。

    3. 因此,我们遍历数组:

      • 如果 left <= nums[i] <= right ,则 last1 = i ;
      • 如果 nums[i] > right ,则 last2 = i,last1 = -1 。

      最后累加 last1 - last2,即完成计算。

  • 相关阅读:
    Swift中的访问控制(Access Control)及断言等知识补充
    asp毕业设计——基于asp+sqlserver的WEB车辆管理系统设计与实现(毕业论文+程序源码)——车辆管理系统
    华为机试真题 C++ 实现【分班问题】
    “双11”来了!企企通B2B商城助力打造供销一体数字化解决方案
    路径中的斜杠与反斜杠
    Android类加载
    docker搭建elk(各组件版本均为7.17.5)所遇问题
    设计模式之兼容不同厂家的相机
    拦截手机号码
    【Vue2.x源码系列04】依赖收集原理(Dep、Watcher、Observer)
  • 原文地址:https://blog.csdn.net/weixin_43894455/article/details/128013480