作者: 负雪明烛
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. MySQL_集群

    管理节点:192.168.31.66 sql节点1+data1节点:192.168.31.42 sql节点2+data2节点:192.168.31.128 llll

  2. LR SP PC

    LR SP PC 深入理解ARM的这三个寄存器,对编程以及操作系统的移植都有很大的裨益. 1.堆栈指针r13(SP):每一种异常模式都有其自己独立的r13,它通常指向异常模式所专用的堆栈,也就是说五种 ...

  3. 8.Maximum Depth of Binary Tree

    /** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode ...

  4. 在 vscode.dev 中直接运行 Python !纯浏览器环境,无后端!

    其实有挺长一段时间没有写自己的 VS Code 插件了! 还是要感谢我们 DevDiv 组的 Flexible Friday 活动,让我可以在工作日研究自己感兴趣的项目. Flexible Frida ...

  5. javaWeb - 3 — JSP (技术已淘汰)— 更新完毕

    1.jsp 在servlet中说过java中前端到后台有两条路线嘛 后台 <------ ajax.json <--------- 前端 后台 <------ jsp( EL.JST ...

  6. EDA简介

    Electronic design automation (EDA), also referred to as electronic computer-aided design (ECAD),[1] ...

  7. 顺序栈(C++)

    栈的定义为只允许在表的末端进行插入和删除的线性表.简而言之就是先进后出的线性表. 插入和删除的一端被称呼为栈顶(top),而不允许插入删除的一端被称为栈底(bottom).无元素时的栈即为空栈. 使用 ...

  8. 【STM32】使用SDIO进行SD卡读写,包含文件管理FatFs(二)-了解SD总线,命令的相关介绍

    其他链接 [STM32]使用SDIO进行SD卡读写,包含文件管理FatFs(一)-初步认识SD卡 [STM32]使用SDIO进行SD卡读写,包含文件管理FatFs(二)-了解SD总线,命令的相关介绍 ...

  9. 【Linux】【Services】【MessageQueue】搭建高可用rabbitMQ

    1. 简介 1.1. 官方网站: https://www.rabbitmq.com/ 1.2. 配置文档:https://docs.openstack.org/ha-guide/shared-mess ...

  10. Redis缓存穿透、缓存击穿以及缓存雪崩

    作为一个内存数据库,redis也总是免不了有各种各样的问题,这篇文章主要是针对其中三个问题进行讲解:缓存穿透.缓存击穿和缓存雪崩.并给出一些解决方案.这三个问题是基本问题也是面试常问问题. 这篇文章我 ...