Skip to content

[pull] main from doocs:main #500

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
252 changes: 202 additions & 50 deletions solution/0800-0899/0845.Longest Mountain in Array/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,18 @@

<!-- 这里可写通用的实现逻辑 -->

**方法一:预处理 + 枚举**

我们定义两个数组 $f$ 和 $g$,其中 $f[i]$ 表示以 $arr[i]$ 结尾的最长上升子序列的长度,而 $g[i]$ 表示以 $arr[i]$ 开头的最长下降子序列的长度。那么对于每个下标 $i$,如果 $f[i] \gt 1$ 且 $g[i] \gt 1$,那么以 $arr[i]$ 为山顶的山脉的长度为 $f[i] + g[i] - 1$,我们只需要枚举所有的 $i$,找出最大的那个值即可。

时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为数组 $arr$ 的长度。

**方法二:一次遍历(枚举左侧山脚)**

我们可以枚举山脉的左侧山脚,然后向右寻找山脉的右侧山脚。我们可以使用两个指针 $l$ 和 $r$,其中 $l$ 表示左侧山脚的下标,$r$ 表示右侧山脚的下标,初始时 $l=0$,$r=0$,然后我们向右移动 $r$,找到山顶的位置,此时判断 $r$ 是否满足 $r + 1 \lt n$ 并且 $arr[r] \gt arr[r + 1]$,如果满足,我们向右继续移动 $r$,直到找到右侧山脚的位置,此时山脉的长度为 $r - l + 1$,我们更新答案,然后将 $l$ 的值更新为 $r$,继续寻找下一个山脉。

时间复杂度 $O(n)$,空间复杂度 $O(1)$。其中 $n$ 为数组 $arr$ 的长度。

<!-- tabs:start -->

### **Python3**
Expand All @@ -69,32 +81,38 @@
```python
class Solution:
def longestMountain(self, arr: List[int]) -> int:
left, right = 0, 1
status = -1
n = len(arr)
f = [1] * n
g = [1] * n
for i in range(1, n):
if arr[i] > arr[i - 1]:
f[i] = f[i - 1] + 1
ans = 0
while right < len(arr):
if status == -1 or status == 1:
if arr[right] == arr[right - 1]:
status = -1
if status == -1:
if arr[right] > arr[right - 1]:
status = 1
else:
left = right
if status == 1 and arr[right] < arr[right - 1]:
status = 2
else:
if arr[right] == arr[right - 1]:
status = -1
ans = max(ans, right - left)
left = right
elif arr[right] > arr[right - 1]:
status = 1
ans = max(ans, right - left)
left = right - 1
right += 1
if status == 2:
ans = max(right - left, ans)
for i in range(n - 2, -1, -1):
if arr[i] > arr[i + 1]:
g[i] = g[i + 1] + 1
if f[i] > 1:
ans = max(ans, f[i] + g[i] - 1)
return ans
```

```python
class Solution:
def longestMountain(self, arr: List[int]) -> int:
n = len(arr)
ans = l = 0
while l + 2 < n:
r = l + 1
if arr[l] < arr[r]:
while r + 1 < n and arr[r] < arr[r + 1]:
r += 1
if r < n - 1 and arr[r] > arr[r + 1]:
while r < n - 1 and arr[r] > arr[r + 1]:
r += 1
ans = max(ans, r - l + 1)
else:
r += 1
l = r
return ans
```

Expand All @@ -105,41 +123,175 @@ class Solution:
```java
class Solution {
public int longestMountain(int[] arr) {
int left = 0, right = 0;
int n = arr.length;
int[] f = new int[n];
int[] g = new int[n];
Arrays.fill(f, 1);
Arrays.fill(g, 1);
for (int i = 1; i < n; ++i) {
if (arr[i] > arr[i - 1]) {
f[i] = f[i - 1] + 1;
}
}
int ans = 0;
int status = -1;
while (++right < arr.length) {
if (status == -1 || status == 1) {
if (arr[right] == arr[right - 1]) {
status = -1;
for (int i = n - 2; i >= 0; --i) {
if (arr[i] > arr[i + 1]) {
g[i] = g[i + 1] + 1;
if (f[i] > 1) {
ans = Math.max(ans, f[i] + g[i] - 1);
}
if (status == -1) {
if (arr[right] > arr[right - 1]) {
status = 1;
} else {
left = right;
}
}
}
return ans;
}
}
```

```java
class Solution {
public int longestMountain(int[] arr) {
int n = arr.length;
int ans = 0;
for (int l = 0, r = 0; l + 2 < n; l = r) {
r = l + 1;
if (arr[l] < arr[r]) {
while (r + 1 < n && arr[r] < arr[r + 1]) {
++r;
}
if (status == 1 && arr[right] < arr[right - 1]) {
status = 2;
if (r + 1 < n && arr[r] > arr[r + 1]) {
while (r + 1 < n && arr[r] > arr[r + 1]) {
++r;
}
ans = Math.max(ans, r - l + 1);
} else {
++r;
}
} else {
if (arr[right] > arr[right - 1]) {
status = 1;
ans = Math.max(right - left, ans);
left = right - 1;
} else if (arr[right] == arr[right - 1]) {
status = -1;
ans = Math.max(right - left, ans);
left = right;
}
}
return ans;
}
}
```

### **C++**

```cpp
class Solution {
public:
int longestMountain(vector<int>& arr) {
int n = arr.size();
int f[n];
int g[n];
fill(f, f + n, 1);
fill(g, g + n, 1);
for (int i = 1; i < n; ++i) {
if (arr[i] > arr[i - 1]) {
f[i] = f[i - 1] + 1;
}
}
int ans = 0;
for (int i = n - 2; ~i; --i) {
if (arr[i] > arr[i + 1]) {
g[i] = g[i + 1] + 1;
if (f[i] > 1) {
ans = max(ans, f[i] + g[i] - 1);
}
}
}
if (status == 2) {
ans = Math.max(ans, right - left);
return ans;
}
};
```

```cpp
class Solution {
public:
int longestMountain(vector<int>& arr) {
int n = arr.size();
int ans = 0;
for (int l = 0, r = 0; l + 2 < n; l = r) {
r = l + 1;
if (arr[l] < arr[r]) {
while (r + 1 < n && arr[r] < arr[r + 1]) {
++r;
}
if (r + 1 < n && arr[r] > arr[r + 1]) {
while (r + 1 < n && arr[r] > arr[r + 1]) {
++r;
}
ans = max(ans, r - l + 1);
} else {
++r;
}
}
}
return ans;
}
};
```

### **Go**

```go
func longestMountain(arr []int) (ans int) {
n := len(arr)
f := make([]int, n)
g := make([]int, n)
for i := range f {
f[i] = 1
g[i] = 1
}
for i := 1; i < n; i++ {
if arr[i] > arr[i-1] {
f[i] = f[i-1] + 1
}
}
for i := n - 2; i >= 0; i-- {
if arr[i] > arr[i+1] {
g[i] = g[i+1] + 1
if f[i] > 1 {
ans = max(ans, f[i]+g[i]-1)
}
}
}
return
}

func max(a, b int) int {
if a > b {
return a
}
return b
}
```

```go
func longestMountain(arr []int) (ans int) {
n := len(arr)
for l, r := 0, 0; l+2 < n; l = r {
r = l + 1
if arr[l] < arr[r] {
for r+1 < n && arr[r] < arr[r+1] {
r++
}
if r+1 < n && arr[r] > arr[r+1] {
for r+1 < n && arr[r] > arr[r+1] {
r++
}
ans = max(ans, r-l+1)
} else {
r++
}
}
}
return
}

func max(a, b int) int {
if a > b {
return a
}
return b
}
```

Expand Down
Loading