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.0
class Solution {
public:
int maxTurbulenceSize(vector<int>& A) {
int len = A.size();
if(len==0)
{
return 0;
}
if(len==1)
{
return 1;
}
int value = A[0];
if(len == count(A.begin(),A.end(),value))
{
return 1;
}
vector<int> dp(len,1);
int conti=0;
for(int i=1;i<len-1;++i)
{
if((A[i-1]>=A[i]&&A[i]>=A[i+1])||(A[i-1]<=A[i]&&A[i]<=A[i+1]))
{
dp[i+1]=dp[i];
conti = 0;
}
if((A[i-1]>A[i]&&A[i]<A[i+1])||(A[i-1]<A[i]&&A[i]>A[i+1]))
{
if(++conti+2 < dp[i])
{
dp[i+1]=dp[i];
}
else
{
dp[i+1]=max(dp[i]+1,conti+2);
}
}
}
return dp[len-1]<2?2:dp[len-1];
}
};
题解思路:
如果 f(k-1)f(k−1) 波形数组的最后一段是“上升”,且 A[k-1] 和 A[k-2] 之间是“上升”,那么 f(k) = 2f(k)=2;
如果 f(k-1)f(k−1) 波形数组的最后一段是“上升”,且 A[k-1] 和 A[k-2] 之间是“下降”,那么 f(k) = f(k-1) + 1f(k)=f(k−1)+1;
如果 f(k-1)f(k−1) 波形数组的最后一段是“下降”,且 A[k-1] 和 A[k-2] 之间是“上升”,那么 f(k) = f(k-1) + 1f(k)=f(k−1)+1;
如果 f(k-1)f(k−1) 波形数组的最后一段是“下降”,且 A[k-1] 和 A[k-2] 之间是“下降”,那么 f(k) = 2f(k)=2;
如果 A[k-1] 和 A[k-2] 之间是“水平”,那么 f(k) = 1f(k)=1;
什么?一个看似简单的问题竟然要分这么多情况考虑,是不是看得头都大了?
通常来说,如果你发现子问题的递推关系过于复杂,那可能是子问题定义得不是很好。既然我们总是要判断波形数组的最后一段是上升还是下降,那我们为何不在子问题定义时就把它们区分开来呢?
是的,我们可以定义两个子问题,分别对应最后一段上升和下降的波形子数组:
子问题 f(k)f(k) 为数组 A[0…k) 中,以 A[k-1] 结尾,且最后一段为“上升”的最长波形子数组;
子问题 g(k)g(k) 为数组 A[0…k) 中,以 A[k-1] 结尾,且最后一段为“下降”的最长波形子数组。
那么我们的子问题递推关系就变得清晰了起来:
如果 A[k-1] 和 A[k-2] 之间是“上升”,那么 f(k) = g(k-1) + 1f(k)=g(k−1)+1,g(k) = 1g(k)=1;
如果 A[k-1] 和 A[k-2] 之间是“下降”,那么 f(k) = 1f(k)=1,g(k) = f(k-1) + 1g(k)=f(k−1)+1;
如果 A[k-1] 和 A[k-2] 之间是“水平”,那么 f(k) = 1f(k)=1,g(k) = 1g(k)=1。
*当子问题非常复杂时,可将子问题分解。
代码2.0:
class Solution {
public:
int maxTurbulenceSize(vector<int>& A) {
int len = A.size();
if (len <= 1 )
{
return len;
}
vector<int> up(len+1, 0);
vector<int> down(len+1, 0);
up[1] = 1;
down[1] = 1;
int res = 1;
for (int i = 2; i <= len; ++i)
{
if (A[i - 2] < A[i-1])
{
up[i] = down[i - 1] + 1;
down[i] = 1;
}
if (A[i - 2] > A[i-1])
{
up[i] = 1;
down[i] = up[i - 1] + 1;
}
if (A[i - 2] == A[i-1])
{
up[i ] = 1;
down[i ] = 1;
}
res = max(res, up[i]);
res = max(res, down[i]);
}
return res;
}
};
res=max(res,up[i])和res=max(res,down[i]);在历次迭代中保存湍流长度的最大值。