动态规划——最长湍流子数组
问题来源:leetcode 978。
最长湍流子数组
当 A
的子数组 A[i], A[i+1], ..., A[j]
满足下列条件时,我们称其为湍流子数组:
- 若
i <= k < j
,当k
为奇数时,A[k] > A[k+1]
,且当k
为偶数时,A[k] < A[k+1]
; - 或 若
i <= k < j
,当k
为偶数时,A[k] > A[k+1]
,且当k
为奇数时,A[k] < A[k+1]
。
也就是说,如果比较符号在子数组中的每个相邻元素对之间翻转,则该子数组是湍流子数组。
返回 A
的最大湍流子数组的长度。
示例 1:
输入:[9,4,2,10,7,8,8,1,9]
输出:5
解释:(A[1] > A[2] < A[3] > A[4] < A[5])
示例 2:
输入:[4,8,12,16]
输出:2
示例 3:
输入:[100]
输出:1
提示:
1 <= A.length <= 40000
0 <= A[i] <= 10^9
动态规划
优化子结构:设以 arr[i]arr[i]arr[i] 为结尾的最长湍流子数组的长度为 nnn,证明该问题的最优解包含其子问题的最优解,或者说该问题的最优解可以由其子问题的最优解构造得到:
- 如果 arr[i]==arr[i−1]arr[i] == arr[i-1]arr[i]==arr[i−1],那么以 arr[i]arr[i]arr[i] 为结尾的最长湍流子数组的长度为 111,不需要子问题的解。
- 如果 arr[i]>arr[i−1]arr[i] > arr[i-1]arr[i]>arr[i−1] 且 arr[i−1]<arr[i−2]arr[i-1] < arr[i-2]arr[i−1]<arr[i−2],那么 n−1n-1n−1 是子问题(以 arr[i−1]arr[i-1]arr[i−1] 为结尾的数组)的最长湍流子数组的长度,也就是说只需要求解该子问题。可以通过反证法证明:假设子问题的最长湍流子数组的长度大于 n−1n-1n−1,那么又因为 arr[i]>arr[i−1]arr[i] > arr[i-1]arr[i]>arr[i−1] 且 arr[i−1]<arr[i−2]arr[i-1] < arr[i-2]arr[i−1]<arr[i−2],所以 arr[i]arr[i]arr[i] 可以接在该湍流子数组的后面,所以以 arr[i]arr[i]arr[i] 为结尾的最长湍流子数组的长度就大于 nnn,与假设矛盾。
- 如果 arr[i]<arr[i−1]arr[i] < arr[i-1]arr[i]<arr[i−1] 且 arr[i−1]>arr[i−2]arr[i-1] > arr[i-2]arr[i−1]>arr[i−2],那么 n−1n-1n−1 是子问题(以 arr[i−1]arr[i-1]arr[i−1] 为结尾的数组)的最长湍流子数组的长度,证明过程与前面相同。
- 对于其他情况(arr[i]>arr[i−1]>arr[i−2]arr[i] > arr[i-1] > arr[i-2]arr[i]>arr[i−1]>arr[i−2] 或 arr[i]<arr[i−1]<arr[i−2]arr[i] < arr[i-1] <arr[i-2]arr[i]<arr[i−1]<arr[i−2]),那么无论以 arr[i−1]arr[i-1]arr[i−1] 为结尾的最长湍流子数组的长度为多少,以 arr[i]arr[i]arr[i] 结尾的最长湍流子数组的长度为 2。
- 还有 arr[i−2]arr[i-2]arr[i−2] 不存在的情况,只需要看 arr[i]arr[i]arr[i] 与 arr[i]arr[i]arr[i] 是否相等,就可以得到原问题的解。
重叠子问题:简单地使用递归算法来求解,很容易发现具有子问题被重复计算。
递归地定义最优解的值:设 dp[i]dp[i]dp[i] 表示以 arr[i]arr[i]arr[i] 结尾的最长湍流子数组的长度,对于数组的每个位置 iii,以该位置元素结尾的最长湍流子数组的长度计算过程如下:
- 首先初始化 dpdpdp 数组的所有位置都为 111。
- 如果 dp[i−1]dp[i-1]dp[i−1] 为 1:
- 如果 arr[i]≠arr[i−1]arr[i] \neq arr[i-1]arr[i]=arr[i−1] 时,dp[i]=2dp[i]=2dp[i]=2;
- 否则保持 111 不变。
- 否则:
- 如果 arr[i]>arr[i−1]arr[i] > arr[i-1]arr[i]>arr[i−1] 且 arr[i−1]<arr[i−2]arr[i-1] < arr[i-2]arr[i−1]<arr[i−2] 或 arr[i]<arr[i−1]arr[i] < arr[i-1]arr[i]<arr[i−1] 且 arr[i−1]>arr[i−2]arr[i-1] > arr[i-2]arr[i−1]>arr[i−2],那么 dp[i]=dp[i−1]+1dp[i] = dp[i-1] + 1dp[i]=dp[i−1]+1;
- 否则看 arr[i−1]arr[i-1]arr[i−1] 与 arr[i]arr[i]arr[i] 是否相等,不相等的话将 dp[i]dp[i]dp[i] 的值置为 222。
自底向上地计算最优解的值:只需要从前向后遍历数组,便可以确保每一个问题计算时,其相关的子问题均已经被计算了出来。
class Solution {public:int maxTurbulenceSize(vector<int>& arr) {int n = arr.size();if(n == 1) {return 1;}vector<int> dp(n, 1);for(int i = 1; i<n; i++) {if(dp[i-1] == 1) {dp[i] = arr[i-1] == arr[i] ? 1 : 2;} else if(arr[i] != arr[i-1]) {if((arr[i] > arr[i-1] && arr[i-1] < arr[i-2]) || (arr[i] < arr[i-1] && arr[i-1] > arr[i-2])) {dp[i] = dp[i-1] + 1;} else {dp[i] = 2;}}}return *max_element(dp.begin(), dp.end());}
};
空间优化:注意到每个 dp[i]dp[i]dp[i] 只与 dp[i−1]dp[i-1]dp[i−1] 相关,所以可以通过一个变量来表示 dpdpdp 数组,另外再通过一个变量保存当前最长湍流子数组的长度即可。
class Solution {public:int maxTurbulenceSize(vector<int>& arr) {int n = arr.size();if(n == 1) {return 1;}int result = 1, temp = 1;for(int i = 1; i<n; i++) {if(temp == 1) {temp = arr[i-1] == arr[i] ? 1 : 2;} else if(arr[i] != arr[i-1]) {if((arr[i] > arr[i-1] && arr[i-1] < arr[i-2]) || (arr[i] < arr[i-1] && arr[i-1] > arr[i-2])) {temp++;} else {temp = 2;}}result = temp > result ? temp : result;}return result;}
};
动态规划——最长湍流子数组相关推荐
- LeetCode——978. 最长湍流子数组(Longest Turbulent Subarray)——分析及代码(Java)
LeetCode--978. 最长湍流子数组[Longest Turbulent Subarray]--分析及代码[Java] 一.题目 二.分析及代码 1. 动态规划(一维数组) (1)思路 (2) ...
- 2021年2月8日 Leetcode每日一题:978. 最长湍流子数组
最长湍流子数组 1.题目描述 当 A 的子数组 A[i], A[i+1], -, A[j] 满足下列条件时,我们称其为湍流子数组: 若 i <= k < j,当 k 为奇数时, A[k] ...
- 算法---最长湍流子数组
题目 最长湍流子数组当 A 的子数组 A[i], A[i+1], ..., A[j] 满足下列条件时,我们称其为湍流子数组:若 i <= k < j,当 k 为奇数时, A[k] > ...
- LeetCode-978:最长湍流子数组
题目描述: 当 A 的子数组 A[i], A[i+1], ..., A[j] 满足下列条件时,我们称其为湍流子数组: 若 i <= k < j,当 k 为奇数时, A[k] > A[ ...
- 湍流参数计算c语言,力扣978.最长湍流子数组-C语言
题目 最长湍流子数组 当 A 的子数组 A[i], A[i+1], ..., A[j] 知足下列条件时,咱们称其为湍流子数组:算法 若 i <= k < j,当 k 为奇数时, A[k] ...
- Leetcode 978. 最长湍流子数组
978. 最长湍流子数组 显示英文描述 我的提交返回竞赛 用户通过次数196 用户尝试次数229 通过次数200 提交次数567 题目难度Medium 当 A 的子数组 A[i], A[i+1], . ...
- LeetCode 978. 最长湍流子数组(DP)
1. 题目 当 A 的子数组 A[i], A[i+1], ..., A[j] 满足下列条件时,我们称其为湍流子数组: 若 i <= k < j,当 k 为奇数时, A[k] > A[ ...
- C++描述 LeetCode 978. 最长湍流子数组
C++描述 LeetCode 978. 最长湍流子数组 大家好,我叫亓官劼(qí guān jié ),在CSDN中记录学习的点滴历程,时光荏苒,未来可期,加油~博主目前仅在CSDN中写博客,唯一 ...
- LeetCode 978 最长湍流子数组
LeetCode 978 最长湍流子数组 题目链接 当 A 的子数组 A[i], A[i+1], -, A[j] 满足下列条件时,我们称其为湍流子数组: 若 i <= k < j,当 k ...
最新文章
- linux中创建本地yum库,轻松安装Linux软件
- ubuntu和windows实现互相之间远程控制
- oracle查询表的索引
- [译]管理IIS日志的存储
- Dapr微服务应用开发系列3:服务调用构件块
- (1)解锁MongoDB replica set核心姿势
- 【框架篇】mvc、mvp、mvvm使用关系总结
- csdn的blog后台程序的导航菜单的实现
- 学习日报 1028 分支结构 if分支语句
- linux中的管道和重定向
- 字符设备驱动(四)按键中断
- 使用 LaTeX 语言对 MATLAB 中的图片进行标注
- Windows平台上使用Qt(MinGW)调用基于VS编写的周立功CAN卡Dll文件
- Python中jieba库的使用
- IOS客户端接入FaceB,SSO授权
- 计算机主板尺寸,电脑主板大中小三个等级的尺寸是多少?
- python结巴怎么安装pip_Python3.6 结巴分词安装和使用
- 前端js华为云obs上传下载文件与进度条的设置
- python双下划线什么意思_python中_、__、__xx__(单下划线、双下划线等)的含义
- linux unix 可视化界面,Linux/UNIX远程调用图形化界面的一种方法
热门文章
- 基于Lucene的中文文本分词
- 【读后感】读《了不起的盖茨比》后感
- 深度学习入门笔记(六):浅层神经网络
- Spring5框架-IOC容器
- java跟踪行为分析_PiggyMetrics
- 第三方开源库:轮播图:Banner/Kanner
- 数据挖掘分析考试笔记
- java格式化时间字符串 毫秒_SimpleDateFormat是否有格式字符串来获取毫秒日期时间值,而不是人类可读的格式?...
- PCB抄板原理图常见错误
- 单系统 台电x80pro_转载:台电X80 Pro Plus 刷Windows10单系统