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;
      }
    };
全部评论

相关推荐

评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务