作者: 负雪明烛
id: fuxuemingzhu
个人博客: http://fuxuemingzhu.cn/


题目地址:https://leetcode.com/problems/number-of-subarrays-with-bounded-maximum/description/

题目描述

We are given an array A of positive integers, and two positive integers L and R (L <= R).

Return the number of (contiguous, non-empty) subarrays such that the value of the maximum array element in that subarray is at least L and at most R.

Example :

Input:
A = [2, 1, 4, 3]
L = 2
R = 3
Output: 3
Explanation: There are three subarrays that meet the requirements: [2], [2, 1], [3].

Note:

  • L, R and A[i] will be an integer in the range [0, 10^9].
  • The length of A will be in the range of [1, 50000].

题目大意

给定了一个数组和L,R两个数字。现在我们要求在这个数组中能有多少个连续的子数组,使得这个子数组的最大值在L和R之间。

解题方法

动态规划

第一感觉是dfs,但是看了下A的长度范围发现基本只能用O(n)的算法了,因此只能使用dp去求了。

我们设定dp数组,其dp[i]的含义是以A[i]为结尾的子数组中满足题目要求的数组个数。所以我们在这个定义的基础上,能得到下面的关系式:

  1. A[i] < L
    这个情况,以A[i]为结尾的子数组的最大值没有改变,因此dp[i] = dp[i - 1]
  2. A[i] > R
    此时,以A[i]为结尾的子数组的最大值已经大于了R,所以dp[i] = 0.把这个位置设定为新的开始,记录该位置为prev.
  3. L <= A[i] <= R
    从prev到i之间的任意起始位置到i的子数组都满足题目条件,因此dp[i] = i - prev.

根据上面的关系式可以写出代码,最后的结果是整个dp之和。

该代码的时间复杂度是O(n),空间复杂度也是O(n)。

代码如下:

class Solution(object):
def numSubarrayBoundedMax(self, A, L, R):
"""
:type A: List[int]
:type L: int
:type R: int
:rtype: int
"""
if not A: return 0
dp = [0] * len(A)
prev = -1
for i, a in enumerate(A):
if a < L and i > 0:
dp[i] = dp[i - 1]
elif a > R:
dp[i] = 0
prev = i
elif L <= a <= R:
dp[i] = i - prev
return sum(dp)

因为dp[i]只和dp[i-1]有关,所以可以把空间复杂度将为O(1)。

class Solution(object):
def numSubarrayBoundedMax(self, A, L, R):
"""
:type A: List[int]
:type L: int
:type R: int
:rtype: int
"""
dp = 0
res = 0
prev = -1
for i, a in enumerate(A):
if a < L and i > 0:
res += dp
elif a > R:
dp = 0
prev = i
elif L <= a <= R:
dp = i - prev
res += dp
return res

暴力搜索+剪枝

如果二重循环可以求出每个数组,但是肯定会超时。不过,如果我们考虑一下剪枝,外层循环里面当前值大于R的时候,就移到下一个位置;内层循环里面,如果当前值大于R,那么后面的全部都不满足,所以直接break掉。这样就能过了!!

class Solution {
public:
int numSubarrayBoundedMax(vector<int>& A, int L, int R) {
const int N = A.size();
int res = 0;
for (int i = 0; i < N; ++i) {
if (A[i] > R) continue;
int curMax = INT_MIN;
for (int j = i; j < N; ++j) {
curMax = max(curMax, A[j]);
if (curMax > R) break;
if (curMax >= L) ++res;
}
}
return res;
}
};

线性遍历

定一个函数count():数组中最大值小于等于bound的子数组个数。所以,我们的最终结果是就是count - count(L-1)。

count函数很好设计,因为只需要线性遍历一次,就知道了。每次遍历的时候,如果当前的值小于等于bound,那么就等于在前面的子数组上又加上了一个新的数组。所以我们需要一个变量来保存前面的数组有多少个了。

class Solution {
public:
int numSubarrayBoundedMax(vector<int>& A, int L, int R) {
return count(A, R) - count(A, L - 1);
}
int count(vector<int>& A, int bound) {
int res = 0, cur = 0;
for (int x : A) {
cur = (x <= bound) ? cur + 1 : 0;
res += cur;
}
return res;
}
};

我最初的想法其实就是双指针,类似虫取法。虽然想法简单,但是如果思路不够清除,根本写不出来。下面就是这个虫取法求子数组的方法。

class Solution {
public:
int numSubarrayBoundedMax(vector<int>& A, int L, int R) {
const int N = A.size();
int res = 0;
int left = -1, right = -1;
for (int i = 0; i < N; ++i) {
if (A[i] > R) left = i;
if (A[i] >= L) right = i;
res += right - left;
}
return res;
}
};

参考资料:
http://www.cnblogs.com/grandyang/p/9237967.html

日期

2018 年 9 月 14 日 —— 现在需要的还是夯实基础,算法和理论
2018 年 12 月 16 日 —— 周赛好难

【LeetCode】795. Number of Subarrays with Bounded Maximum 解题报告(Python & C++)的更多相关文章

  1. LeetCode 795. Number of Subarrays with Bounded Maximum

    问题链接 LeetCode 795 题目解析 给定一个数组A,左右范围L.R.求子数组的数量,要求:子数组最大值在L.R之间. 解题思路 子数组必须连续,利用最大值R对数组进行分段,设定变量 left ...

  2. 795. Number of Subarrays with Bounded Maximum

    数学的方式 是对于所有的字符分成简单的三类 0 小于 L 1 LR 之间 2 大于R 也就是再求 不包含 2 但是包含1 的子数组个数 不包含2的子数组个数好求 对于连续的相邻的n个 非2类数 就有 ...

  3. [LeetCode] Number of Subarrays with Bounded Maximum 有界限最大值的子数组数量

    We are given an array A of positive integers, and two positive integers L and R (L <= R). Return ...

  4. 74th LeetCode Weekly Contest Number of Subarrays with Bounded Maximum

    We are given an array A of positive integers, and two positive integers L and R (L <= R). Return ...

  5. [Swift]LeetCode795. 区间子数组个数 | Number of Subarrays with Bounded Maximum

    We are given an array A of positive integers, and two positive integers L and R (L <= R). Return ...

  6. LeetCode 806 Number of Lines To Write String 解题报告

    题目要求 We are to write the letters of a given string S, from left to right into lines. Each line has m ...

  7. 【LeetCode】26. Remove Duplicates from Sorted Array 解题报告(Python&C++&Java)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 双指针 日期 [LeetCode] https:// ...

  8. 【LeetCode】450. Delete Node in a BST 解题报告 (Python&C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 迭代 日期 题目地址:https://leetcode ...

  9. 【LeetCode】452. Minimum Number of Arrows to Burst Balloons 解题报告(Python)

    [LeetCode]452. Minimum Number of Arrows to Burst Balloons 解题报告(Python) 标签(空格分隔): LeetCode 题目地址:https ...

随机推荐

  1. nginx负均

    Nginx负载均衡详解 上一篇中我说啦nginx有哪些中负载均衡算法.这一结我就给如果操作配置的给大家做详细说明下. 首先给大家说下upstream这个配置的,这个配置是写一组被代理的服务器地址,然后 ...

  2. Hosts文件详解

    一.缘由 关于我们工作室项目配置过程中,有一个重要但却容易被忽略的环节 - hosts文件的修改. 之前配置hosts文件的时候,只知道那么做就可以了,但并不知道其中的原因,由于开发任务的急迫,也就未 ...

  3. CentOS6配置邮件发送

    CentOS6配置邮件发送 注意:要启用邮箱的服务端授权代理功能,并从中获取授权码 \cp /etc/mail.rc{,.bak} # 备份配置文件 cat >>/etc/mail.rc& ...

  4. Python获取随机数

    Python当中,可用random模块来获取随机数 import random """ random模块,用于获取随机数 """ print ...

  5. PDFium 渲染

    PDFium 是 Chromium 的 PDF 渲染引擎,许可协议为 BSD 3-Clause.不同于 Mozilla 基于 HTML5 的 PDF.js,PDFium 是基于 Foxit Softw ...

  6. 学会这几步,简单集成视频编辑原子能力SDK

    华为视频编辑服务6.2.0版本上线后,我们为大家带来了两大变化:分别是丰富多样的AI能力和灵活选择的集成方式.为让开发者更快上手使用,今天小编带来了视频编辑原子能力SDK的具体集成方法.快来试试吧! ...

  7. HTML样式 背景

    当浏览器读到一个样式表,就会按照这个格式表来对文档进行格式化.有以下三种方式来插入样式表: 1.外部样式表 当样式需要用到很多页面的时候,外部样式是理想的选择.使用外部样式表,就可以听过更改一个文件来 ...

  8. SVN的基本介绍\服务器配置

    ### 1. 工作场景 1. 进入公司需要做的关于开发的第一件事, 就是向项目经理索要SVN服务器地址+用户名+密码### 2. 角色解释> 服务器: 用于存放所有版本的代码,供客户端上传下载更 ...

  9. Linux上用Jexus部署Asp.Net网站:常规部署与Docker部署

    (一)常规部署 一.把 jexus压缩包下载到linux临时文件夹中. cd /tmp wget linuxdot.net/down/jexus-6.2.x-arm64.tar.gz (不同的操作系统 ...

  10. OceanBase 2.x体验:推荐用DBeaver工具连接数据库

    Original MQ4096 [OceanBase技术闲谈](javascript:void(0) 2020-01-15 OceanBase 2.x体验:推荐用DBeaver工具连接数据库 Ocea ...