Let's call any (contiguous) subarray B (of A) a mountain if the following properties hold:

  • B.length >= 3
  • There exists some 0 < i < B.length - 1 such that B[0] < B[1] < ... B[i-1] < B[i] > B[i+1] > ... > B[B.length - 1]

(Note that B could be any subarray of A, including the entire array A.)

Given an array A of integers, return the length of the longest mountain.

Return 0 if there is no mountain.

Example 1:

Input: [2,1,4,7,3,2,5]
Output: 5
Explanation: The largest mountain is [1,4,7,3,2] which has length 5.

Example 2:

Input: [2,2,2]
Output: 0
Explanation: There is no mountain.

Note:

  1. 0 <= A.length <= 10000
  2. 0 <= A[i] <= 10000

Follow up:

  • Can you solve it using only one pass?
  • Can you solve it in O(1) space?

这道题给了我们一个数组,然后定义了一种像山一样的子数组,就是先递增再递减的子数组,注意这里是强行递增或者递减的,并不存在相等的情况。那么实际上这道题就是让在数组中寻找一个位置,使得以此位置为终点的递增数组和以此位置为起点的递减数组的长度最大。而以某个位置为起点的递减数组,如果反个方向来看,其实就是就该位置为终点的递增数列,那么既然都是求最长的递增数列,我们可以分别用两个 dp 数组 up 和 down,其中 up[i] 表示以 i 位置为终点的最长递增数列的个数,down[i] 表示以 i 位置为起点的最长递减数列的个数,这样我们正向更新 up 数组,反向更新 down 数组即可。先反向更新好了 down 之后,在正向更新 up 数组的同时,也可以更新结果 res,当某个位置的 up[i] 和 down[i] 均大于0的时候,那么就可以用 up[i] + down[i] + 1 来更新结果 res 了,参见代码如下:

解法一:

class Solution {
public:
int longestMountain(vector<int>& A) {
int res = , n = A.size();
vector<int> up(n), down(n);
for (int i = n - ; i >= ; --i) {
if (A[i] > A[i + ]) down[i] = down[i + ] + ;
}
for (int i = ; i < n; ++i) {
if (A[i] > A[i - ]) up[i] = up[i - ] + ;
if (up[i] > && down[i] > ) res = max(res, up[i] + down[i] + );
}
return res;
}
};

我们可以对空间进行优化,不必使用两个数组来记录所有位置的信息,而是只用两个变量 up 和 down 来分别记录以当前位置为终点的最长递增数列的长度,和以当前位置为终点的最长递减数列的长度。 我们从 i=1 的位置开始遍历,因为山必须要有上坡和下坡,所以 i=0 的位置永远不可能成为 peak。此时再看,如果当前位置跟前面的位置相等了,那么当前位置的 up 和 down 都要重置为0,从当前位置开始找新的山,和之前的应该断开。或者是当 down 不为0,说明此时是在下坡,如果当前位置大于之前的了,突然变上坡了,那么之前的累计也需要重置为0。然后当前位置再进行判断,若大于前一个位置,则是上坡,up 自增1,若小于前一个位置,是下坡,down 自增1。当 up 和 down 同时为正数,则用 up+down+1 来更新结果 res 即可,参见代码如下:

解法二:

class Solution {
public:
int longestMountain(vector<int>& A) {
int res = , up = , down = , n = A.size();
for (int i = ; i < n; ++i) {
if ((down && A[i - ] < A[i]) || (A[i - ] == A[i])) {
up = down = ;
}
if (A[i - ] < A[i]) ++up;
if (A[i - ] > A[i]) ++down;
if (up > && down > ) res = max(res, up + down + );
}
return res;
}
};

我们可以换一种思路,还是一次遍历就行,进行 while 循环,条件是 i < n-1,然后判断,当前数字大于等于下一个数字则跳过,因为我们希望首先上坡,当找到递增的起点i后,则再开始循环,找山顶 peak,找到了之后,再进行下坡,找到山脚j,这样如果i,peak,和j都不相同的话,说明找到了一个完整的山,用 j-i+1 来更新结果 res 即可,然后i从j开始继续遍历,参见代码如下:

解法三:

class Solution {
public:
int longestMountain(vector<int>& A) {
int res = , i = , n = A.size();
while (i < n - ) {
while (i < n - && A[i] >= A[i + ]) ++i;
int peak = i;
while (peak < n - && A[peak] < A[peak + ]) ++peak;
int j = peak;
while (j < n - && A[j] > A[j + ]) ++j;
if (i < peak && peak < j) res = max(res, j - i + );
i = j;
}
return res;
}
};

也可以再换种思路,首先来找山峰,peak 的范围是 [1, n-1],因为首尾两个数字都不能做山峰,能做山峰的位置上的数必须大于其左右两边的数字,然后分别向左右两个方向遍历,这样就可以找到完整的山,用 right-left+1 来更新结果 res,参见代码如下:

解法四:

class Solution {
public:
int longestMountain(vector<int>& A) {
int res = , n = A.size();
for (int i = ; i < n - ; ++i) {
if (A[i - ] < A[i] && A[i + ] < A[i]) {
int left = i - , right = i + ;
while (left > && A[left - ] < A[left]) --left;
while (right < n - && A[right] > A[right + ]) ++right;
res = max(res, right - left + );
}
}
return res;
}
};

Github 同步地址:

https://github.com/grandyang/leetcode/issues/845

参考资料:

https://leetcode.com/problems/longest-mountain-in-array/

https://leetcode.com/problems/longest-mountain-in-array/discuss/176952/Java-1-pass-and-O(1)-space-beats-100

https://leetcode.com/problems/longest-mountain-in-array/discuss/135593/C%2B%2BJavaPython-1-pass-and-O(1)-space

https://leetcode.com/problems/longest-mountain-in-array/discuss/150136/Simple-O(n)-one-pass-O(1)-space-Java-AC-solution-beats-99.05

LeetCode All in One 题目讲解汇总(持续更新中...)

[LeetCode] Longest Mountain in Array 数组中最长的山的更多相关文章

  1. Longest Mountain in Array 数组中的最长山脉

    我们把数组 A 中符合下列属性的任意连续子数组 B 称为 “山脉”: B.length >= 3 存在 0 < i < B.length - 1 使得 B[0] < B[1] ...

  2. 【LeetCode】845. Longest Mountain in Array 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 双数组 参考资料 日期 题目地址:https://l ...

  3. LeetCode第十四题-字符串数组中最长的共同前缀

    Longest Common Prefix 问题简介: 编写一个函数来查找字符串数组中最长的公共前缀字符串,如果没有公共前缀,则返回空字符串"" 举例: 1: 输入: [“xwq” ...

  4. 014 Longest Common Prefix 查找字符串数组中最长的公共前缀字符串

    编写一个函数来查找字符串数组中最长的公共前缀字符串. 详见:https://leetcode.com/problems/longest-common-prefix/description/ 实现语言: ...

  5. LeetCode:寻找旋转排序数组中的最小值【153】

    LeetCode:寻找旋转排序数组中的最小值[153] 题目描述 假设按照升序排序的数组在预先未知的某个点上进行了旋转. ( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0 ...

  6. [Swift]LeetCode845. 数组中的最长山脉 | Longest Mountain in Array

    Let's call any (contiguous) subarray B (of A) a mountain if the following properties hold: B.length ...

  7. [LeetCode] Kth Largest Element in an Array 数组中第k大的数字

    Find the kth largest element in an unsorted array. Note that it is the kth largest element in the so ...

  8. [LeetCode] K-diff Pairs in an Array 数组中差为K的数对

    Given an array of integers and an integer k, you need to find the number of unique k-diff pairs in t ...

  9. [LeetCode] 215. Kth Largest Element in an Array 数组中第k大的数字

    Find the kth largest element in an unsorted array. Note that it is the kth largest element in the so ...

随机推荐

  1. 二值化神经网络(BNN)基础学习(一)

    目录 1.简介 2.优点 3.基本原理 3.1 权重和激活值二值化[3] 3.2 乘法优化 3.3 权重和激活值更新 4.结论[3] 参考资料 1.简介 ​ 二值化神经网络,在浮点型(权重值和激活函数 ...

  2. Leetcode-1.两数之和

    题目描述: 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标. 你可以假设每种输入只会对应一个答案.但是,你不能重复利用这个数 ...

  3. Linux kill 命令 以及USR1 信号解释

    kill 中的USR信号解释 USR1亦通常被用来告知应用程序重载配置文件:例如,向Apache HTTP服务器发送一个USR1信号将导致以下步骤的发生:停止接受新的连接,等待当前连接停止,重新载入配 ...

  4. TinyMCE

    段落段落段落段落 标题1 标题2 标题3 标题4 标题5 标题6

  5. Oracle 数据库监听无法连接上、监听HANG住、监听无响应、TNS-12560

    环境: Windows server 2003 Oracle 11.2.0.1 问题: 一套老数据库在运行了很久后,突然就连接不上了,提示监听异常. 处理: 1.CMD命令行检查监听状态:无监听 2. ...

  6. unity iOS本地代码总结(一)

    1. 项目能直接运行了,但是代码的实际数据流动任然会有问题. 2. unity的代码能这么简单的被调用简直是奇迹一样,不需要大的改动就能够使用. 3. 目前需要注意的问题就是,unity的内容还太少, ...

  7. ios访问web页面<div>点击事件不起效果,以及alert()显示url的解决办法

    ios访问web页面<div>点击不起效果,在其div上添加style=”cursor:pointer:“ jquery web页面动态append()事件调用方法:$(document) ...

  8. spring boot mybatis打印SQL语句

    在logback-spring.xml 文件中添加 <logger name="com.ibatis" level="DEBUG" /> <l ...

  9. navicat连接centos7上mysql:2003-Can't connect to MySQL server (10060)

    问题解决步骤: 1.参考http://jingyan.baidu.com/article/95c9d20dac9040ec4f75617a.html,发现是防火墙未关闭: 2.关闭并禁止firewal ...

  10. C#实现视频监控客户端onvif协议一

    前言 最近做的项目是监控方面的,需要对接各种摄像头,之前的方案是把各个厂家的SDK都集成到系统中,然后让用户进行切换,后来知道了Onvif (自行百度具体概念)这个东西.原来早就有人一统江湖了. on ...