Leetcode刷题记录DP-01
1. 题目描述
1.1 我们把数组 A 中符合下列属性的任意连续子数组 B 称为 “山脉”:
- B.length >= 3
- 存在 0 < i < B.length - 1 使得 B[0] < B[1] < ... B[i-1] < B[i] > B[i+1] > ... > B[B.length - 1]
(注意:B 可以是 A 的任意子数组,包括整个数组 A。) - 给出一个整数数组 A,返回最长 “山脉” 的长度。
- 如果不含有 “山脉” 则返回 0。
1.2 示例
输入:[2,1,4,7,3,2,5] 输出:5 解释:最长的 “山脉” 是 [1,4,7,3,2],长度为 5。
1.3 提示
0 <= A.length <= 10000 0 <= A[i] <= 10000
2. 解答 (动态规划)
这个题是最长递增子序列的进阶版,思考方式还是一样,包括状态表示与状态计算,其中状态表示包括集合和属性,集合这里要分为两个部分,从左往右以i结尾的递增的子序列的长度,以及包括以i结尾从右往左递减的序列,所得到的的“山脉”长度为dp[i] (左)+dp[i] (右) -1. 这里属性即为所有“山脉”长度的最大值。
left[i] 表示 A[i] 向左最多扩展的元素个数
right[i] 表示 A[i] 向右最多扩展的元素个数
最后枚举山顶,left[i] 和 right[i] 都大于 0 时 A[i] 才可以作为山顶
class Solution { public: int longestMountain(vector<int>& A) { int n = A.size(); if (n == 0) { return 0; } vector<int> left(n); for (int i = 1; i < n; ++i) { left[i] = A[i - 1] < A[i] ? left[i - 1] + 1 : 0; } vector<int> right(n); for (int i = n - 2; i >= 0; --i) { right[i] = A[i + 1] < A[i] ? right[i + 1] + 1 : 0; } int ans = 0; for (int i = 0; i < n; ++i) { if (left[i] > 0 && right[i] > 0) { ans = max(ans, left[i] + right[i] + 1); } } return ans; } };