A sequence of integers
is said to be UpDown, if the inequality
holds true.
You are given a sequence
. You can insert at most one integer in the sequence. It could be any integer. Find the length of the longest subsegment of the new sequence after adding an integer (or choosing not to) which is UpDown.
A subsegment is a consecutive portion of a sequence. That is, a subsegment of
will be of the form
for some
and
.
This problem was asked in Zonal Computing Olympiad 2019.
Examples:
Input: arr[] = {1, 10, 3, 20, 25, 24}
Output: 7
Suppose we insert 5 between 20 and 25, the whole sequence (1, 10, 3, 20, 5, 25, 24)
becomes an UpDown Sequence and hence the answer is 7.
Input: arr[] = {100, 1, 10, 3, 4, 6, 11}
Output: 6
Suppose we insert 4 between 4 and 6, the sequence (1, 10, 3, 4, 4, 6) becomes an UpDown
Sequence and hence the answer is 6. We can verify that this is the best possible
solution.
Approach: Let us begin by defining two types of sequence:-
- UpDown Sequence (UD) : A sequence of the form
That is, the sequence starts by increasing first.
- DownUp Sequence (DU) : A sequence of the form
That is, the sequence starts by decreasing first.
Let us first find out the length of UD and DU sequences without thinking about other parts of the problem. For that, let us define
to be the longest UpDown sequence beginning at
and
to be the longest DownUp sequence beginning at
.
Recurrence relation for
is :-
(1) 
Here, N is the length of the sequence and state is either 1 or 2 and stands for UD and DU sequence respectively. While forming the recurrence relation, we used the fact that In an UD sequence
, the part
is a DU sequence and vice-versa. We can use Dynamic Programming to calculate the value of
and then store our result in array dp[N][2].
Now, notice that it is always possible to insert an integer at the end of an UpDown sequence to increase the length of the sequence by 1 and yet retain the UpDown inequality. Why ? Suppose an UD sequence breaks at
because
when we expected it to be
. We can insert an integer
between
and
. Now,
is satisfied.
We can give similar argument for the case when UD sequence breaks at
because
when we expected it to be
. But we don’t have to actually insert anything. We have to just find the length of the longest UD sequence possible.
Observe that a UD sequence is a combination of :-
- UD sequence I + x + UD sequence II if the length of UD sequence I is odd
- UD sequence I + x + DU sequence I if the length of UD sequence I is even
where, x is the inserted element.
So for each i, we calculate the length of the longest UD sequence starting at i. Let that length be y.
If y is odd, we insert an element there (theoretically) and calculate the length of longest UD sequence starting at i+y. The longest UD sequence beginning at i after inserting an element is therefore dp[i][1] + 1 + dp[i+y][1].
If y is even, we insert an element there (theoretically) and calculate the length of longest DU sequence starting at i+y. The longest UD sequence beginning at i after inserting an element is therefore dp[i][1] + 1 + dp[i+y][2].
The final answer is maximum such value among all i.
C++
#include <bits/stdc++.h>
using namespace std;
int f( int i, int state, int A[], int dp[][3], int N)
{
if (i >= N)
return 0;
else if (dp[i][state] != -1) {
return dp[i][state];
}
else {
if (i == N - 1)
dp[i][state] = 1;
else if (state == 1 && A[i] > A[i + 1])
dp[i][state] = 1;
else if (state == 2 && A[i] < A[i + 1])
dp[i][state] = 1;
else if (state == 1 && A[i] <= A[i + 1])
dp[i][state] = 1 + f(i + 1, 2, A, dp, N);
else if (state == 2 && A[i] >= A[i + 1])
dp[i][state] = 1 + f(i + 1, 1, A, dp, N);
return dp[i][state];
}
}
int maxLenSeq( int A[], int N)
{
int i, tmp, y, ans;
int dp[1000][3];
memset (dp, -1, sizeof dp);
for (i = 0; i < N; i++) {
tmp = f(i, 1, A, dp, N);
tmp = f(i, 2, A, dp, N);
}
ans = -1;
for (i = 0; i < N; i++) {
y = dp[i][1];
if (i + y >= N)
ans = max(ans, dp[i][1] + 1);
else if (y % 2 == 0) {
ans = max(ans, dp[i][1] + 1 + dp[i + y][2]);
}
else if (y % 2 == 1) {
ans = max(ans, dp[i][1] + 1 + dp[i + y][1]);
}
}
return ans;
}
int main()
{
int A[] = { 1, 10, 3, 20, 25, 24 };
int n = sizeof (A) / sizeof ( int );
cout << maxLenSeq(A, n);
return 0;
}
|
Java
import java.io.*;
public class GFG
{
static int f( int i, int state, int A[],
int dp[][], int N)
{
if (i >= N)
return 0 ;
else if (dp[i][state] != - 1 )
{
return dp[i][state];
}
else
{
if (i == N - 1 )
dp[i][state] = 1 ;
else if (state == 1 && A[i] > A[i + 1 ])
dp[i][state] = 1 ;
else if (state == 2 && A[i] < A[i + 1 ])
dp[i][state] = 1 ;
else if (state == 1 && A[i] <= A[i + 1 ])
dp[i][state] = 1 + f(i + 1 , 2 , A, dp, N);
else if (state == 2 && A[i] >= A[i + 1 ])
dp[i][state] = 1 + f(i + 1 , 1 , A, dp, N);
return dp[i][state];
}
}
static int maxLenSeq( int A[], int N)
{
int i,j, tmp, y, ans;
int dp[][] = new int [ 1000 ][ 3 ];
for (i= 0 ; i < 1000 ; i++)
for (j = 0 ; j < 3 ; j++)
dp[i][j] = - 1 ;
for (i = 0 ; i < N; i++)
{
tmp = f(i, 1 , A, dp, N);
tmp = f(i, 2 , A, dp, N);
}
ans = - 1 ;
for (i = 0 ; i < N; i++)
{
y = dp[i][ 1 ];
if (i + y >= N)
ans = Math.max(ans, dp[i][ 1 ] + 1 );
else if (y % 2 == 0 )
{
ans = Math.max(ans, dp[i][ 1 ] + 1 + dp[i + y][ 2 ]);
}
else if (y % 2 == 1 )
{
ans = Math.max(ans, dp[i][ 1 ] + 1 + dp[i + y][ 1 ]);
}
}
return ans;
}
public static void main (String[] args)
{
int A[] = { 1 , 10 , 3 , 20 , 25 , 24 };
int n = A.length;
System.out.println(maxLenSeq(A, n));
}
}
|
Python3
def f(i, state, A, dp, N):
if i > = N:
return 0
elif dp[i][state] ! = - 1 :
return dp[i][state]
else :
if i = = N - 1 :
dp[i][state] = 1
elif state = = 1 and A[i] > A[i + 1 ]:
dp[i][state] = 1
elif state = = 2 and A[i] < A[i + 1 ]:
dp[i][state] = 1
elif state = = 1 and A[i] < = A[i + 1 ]:
dp[i][state] = 1 + f(i + 1 , 2 , A, dp, N)
elif state = = 2 and A[i] > = A[i + 1 ]:
dp[i][state] = 1 + f(i + 1 , 1 , A, dp, N)
return dp[i][state]
def maxLenSeq(A, N):
dp = [[ - 1 , - 1 , - 1 ] for i in range ( 1000 )]
for i in range (N):
tmp = f(i, 1 , A, dp, N)
tmp = f(i, 2 , A, dp, N)
ans = - 1
for i in range (N):
y = dp[i][ 1 ]
if (i + y) > = N:
ans = max (ans, dp[i][ 1 ] + 1 )
elif y % 2 = = 0 :
ans = max (ans, dp[i][ 1 ] + 1 + dp[i + y][ 2 ])
elif y % 2 = = 1 :
ans = max (ans, dp[i][ 1 ] + 1 + dp[i + y][ 1 ])
return ans
if __name__ = = "__main__" :
A = [ 1 , 10 , 3 , 20 , 25 , 24 ]
n = len (A)
print (maxLenSeq(A, n))
|
C#
using System;
class GFG
{
static int f( int i, int state, int []A,
int [,]dp, int N)
{
if (i >= N)
return 0;
else if (dp[i, state] != -1)
{
return dp[i, state];
}
else
{
if (i == N - 1)
dp[i, state] = 1;
else if (state == 1 && A[i] > A[i + 1])
dp[i, state] = 1;
else if (state == 2 && A[i] < A[i + 1])
dp[i, state] = 1;
else if (state == 1 && A[i] <= A[i + 1])
dp[i, state] = 1 + f(i + 1, 2, A, dp, N);
else if (state == 2 && A[i] >= A[i + 1])
dp[i, state] = 1 + f(i + 1, 1, A, dp, N);
return dp[i, state];
}
}
static int maxLenSeq( int []A, int N)
{
int i, j, tmp, y, ans;
int [,]dp = new int [1000, 3];
for (i = 0; i < 1000; i++)
for (j = 0; j < 3; j++)
dp[i, j] = -1;
for (i = 0; i < N; i++)
{
tmp = f(i, 1, A, dp, N);
tmp = f(i, 2, A, dp, N);
}
ans = -1;
for (i = 0; i < N; i++)
{
y = dp[i, 1];
if (i + y >= N)
ans = Math.Max(ans, dp[i, 1] + 1);
else if (y % 2 == 0)
{
ans = Math.Max(ans, dp[i, 1] + 1 +
dp[i + y, 2]);
}
else if (y % 2 == 1)
{
ans = Math.Max(ans, dp[i, 1] + 1 +
dp[i + y, 1]);
}
}
return ans;
}
public static void Main (String[] args)
{
int []A = { 1, 10, 3, 20, 25, 24 };
int n = A.Length;
Console.WriteLine(maxLenSeq(A, n));
}
}
|
Javascript
<script>
function f(i, state, A, dp, N)
{
if (i >= N)
return 0;
else if (dp[i][state] != -1)
{
return dp[i][state];
}
else
{
if (i == N - 1)
dp[i][state] = 1;
else if (state == 1 && A[i] > A[i + 1])
dp[i][state] = 1;
else if (state == 2 && A[i] < A[i + 1])
dp[i][state] = 1;
else if (state == 1 && A[i] <= A[i + 1])
dp[i][state] = 1 + f(i + 1, 2, A, dp, N);
else if (state == 2 && A[i] >= A[i + 1])
dp[i][state] = 1 + f(i + 1, 1, A, dp, N);
return dp[i][state];
}
}
function maxLenSeq(A, N)
{
let i,j, tmp, y, ans;
let dp = new Array(1000);
for (i= 0; i < 1000; i++)
{
dp[i] = new Array(3);
for (j = 0; j < 3; j++)
{
dp[i][j] = -1;
}
}
for (i = 0; i < N; i++)
{
tmp = f(i, 1, A, dp, N);
tmp = f(i, 2, A, dp, N);
}
ans = -1;
for (i = 0; i < N; i++)
{
y = dp[i][1];
if (i + y >= N)
ans = Math.max(ans, dp[i][1] + 1);
else if (y % 2 == 0)
{
ans = Math.max(ans, dp[i][1] + 1 + dp[i + y][2]);
}
else if (y % 2 == 1)
{
ans = Math.max(ans, dp[i][1] + 1 + dp[i + y][1]);
}
}
return ans;
}
let A = [ 1, 10, 3, 20, 25, 24 ];
let n = A.length;
document.write(maxLenSeq(A, n));
</script>
|
Time Complexity: O(n)
Space Complexity: O(n)
Feeling lost in the world of random DSA topics, wasting time without progress? It's time for a change! Join our DSA course, where we'll guide you on an exciting journey to master DSA efficiently and on schedule.
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 geeks!
Last Updated :
01 Nov, 2023
Like Article
Save Article