整数序列如果不等式被称为UpDown 成立。
给你一个序列 。您最多可以在序列中插入一个整数。它可以是任何整数。在添加整数(或选择不添加)UpDown之后,找到新序列的最长子段的长度。
子段是序列的连续部分。也就是说, 将采用以下形式对于一些和 。
在2019年的Zonal Computing Olympiad中提出了这个问题。
例子:
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.
方法:让我们从定义两种类型的序列开始:
- UpDown Sequence(UD):形式的序列即,先后顺序是先增加后再开始。
- DownUp Sequence(DU):形式的序列即,先从先减小顺序开始。
让我们首先找出UD和DU序列的长度,而无需考虑问题的其他部分。为此,让我们定义开始于最长的UpDown序列和开始于最长的DownUp序列 。
的递归关系是 :-
(1)
在此,N是序列的长度,状态是1或2,分别代表UD和DU序列。在形成递归关系时,我们使用了以下事实:在UD序列中 , 那个部分是DU序列,反之亦然。我们可以使用动态编程来计算然后将结果存储在数组dp [N] [2]中。
现在,请注意,始终可以在UpDown序列的末尾插入一个整数,以将序列的长度增加1,但仍保留UpDown不等式。为什么 ?假设UD序列在处中断因为当我们期望它是 。我们可以插入一个整数之间和 。现在, 很满意。
对于UD序列在处中断的情况,我们可以给出类似的论点因为当我们期望它是 。但是,我们不必实际插入任何内容。我们必须找到可能的最长UD序列的长度。
请注意,UD序列是以下各项的组合:
- 如果UD序列I的长度为奇数,则UD序列I + x + UD序列II
- 如果UD序列I的长度是偶数,则UD序列I + x + DU序列I
其中,x是插入的元素。
因此,对于每个i,我们计算从i开始的最长UD序列的长度。令长度为y。
如果y为奇数,则在理论上将一个元素插入其中,并计算从i + y开始的最长UD序列的长度。因此,在插入元素后从i开始的最长UD序列为dp [i] [1] +1 + dp [i + y] [1] 。
如果y为偶数,则在理论上将一个元素插入那里,然后计算从i + y开始的最长DU序列的长度。因此,在插入元素后从i开始的最长UD序列为dp [i] [1] + 1 + dp [i + y] [2] 。
最终答案是在所有i中最大的这样的值。
C++
// C++ implementation of the approach
#include
using namespace std;
// Function to recursively fill the dp array
int f(int i, int state, int A[], int dp[][3], int N)
{
if (i >= N)
return 0;
// If f(i, state) is already calculated
// then return the value
else if (dp[i][state] != -1) {
return dp[i][state];
}
// Calculate f(i, state) according to the
// recurrence relation and store in dp[][]
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 that calls the resucrsive function to
// fill the dp array and then returns the result
int maxLenSeq(int A[], int N)
{
int i, tmp, y, ans;
// dp[][] array for storing result
// of f(i, 1) and f(1, 2)
int dp[1000][3];
// Populating the array dp[] with -1
memset(dp, -1, sizeof dp);
// Make sure that longest UD and DU
// sequence starting at each
// index is calculated
for (i = 0; i < N; i++) {
tmp = f(i, 1, A, dp, N);
tmp = f(i, 2, A, dp, N);
}
// Assume the answer to be -1
// This value will only increase
ans = -1;
for (i = 0; i < N; i++) {
// y is the length of the longest
// UD sequence starting at i
y = dp[i][1];
if (i + y >= N)
ans = max(ans, dp[i][1] + 1);
// If length is even then add an integer
// and then a DU sequence starting at i + y
else if (y % 2 == 0) {
ans = max(ans, dp[i][1] + 1 + dp[i + y][2]);
}
// If length is odd then add an integer
// and then a UD sequence starting at i + y
else if (y % 2 == 1) {
ans = max(ans, dp[i][1] + 1 + dp[i + y][1]);
}
}
return ans;
}
// Driver code
int main()
{
int A[] = { 1, 10, 3, 20, 25, 24 };
int n = sizeof(A) / sizeof(int);
cout << maxLenSeq(A, n);
return 0;
}
Java
// Java implementation of the approach
class GFG
{
// Function to recursively fill the dp array
static int f(int i, int state, int A[],
int dp[][], int N)
{
if (i >= N)
return 0;
// If f(i, state) is already calculated
// then return the value
else if (dp[i][state] != -1)
{
return dp[i][state];
}
// Calculate f(i, state) according to the
// recurrence relation and store in dp[][]
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 that calls the resucrsive function to
// fill the dp array and then returns the result
static int maxLenSeq(int A[], int N)
{
int i,j, tmp, y, ans;
// dp[][] array for storing result
// of f(i, 1) and f(1, 2)
int dp[][] = new int[1000][3];
// Populating the array dp[] with -1
for(i= 0; i < 1000; i++)
for(j = 0; j < 3; j++)
dp[i][j] = -1;
// Make sure that longest UD and DU
// sequence starting at each
// index is calculated
for (i = 0; i < N; i++)
{
tmp = f(i, 1, A, dp, N);
tmp = f(i, 2, A, dp, N);
}
// Assume the answer to be -1
// This value will only increase
ans = -1;
for (i = 0; i < N; i++)
{
// y is the length of the longest
// UD sequence starting at i
y = dp[i][1];
if (i + y >= N)
ans = Math.max(ans, dp[i][1] + 1);
// If length is even then add an integer
// and then a DU sequence starting at i + y
else if (y % 2 == 0)
{
ans = Math.max(ans, dp[i][1] + 1 + dp[i + y][2]);
}
// If length is odd then add an integer
// and then a UD sequence starting at i + y
else if (y % 2 == 1)
{
ans = Math.max(ans, dp[i][1] + 1 + dp[i + y][1]);
}
}
return ans;
}
// Driver code
public static void main (String[] args)
{
int A[] = { 1, 10, 3, 20, 25, 24 };
int n = A.length;
System.out.println(maxLenSeq(A, n));
}
}
// This code is contributed by AnkitRai01
Python3
# Python3 implementation of the approach
# Function to recursively fill the dp array
def f(i, state, A, dp, N):
if i >= N:
return 0
# If f(i, state) is already calculated
# then return the value
elif dp[i][state] != -1:
return dp[i][state]
# Calculate f(i, state) according to the
# recurrence relation and store in dp[][]
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]
# Function that calls the resucrsive function to
# fill the dp array and then returns the result
def maxLenSeq(A, N):
# dp[][] array for storing result
# of f(i, 1) and f(1, 2)
# Populating the array dp[] with -1
dp = [[-1, -1, -1] for i in range(1000)]
# Make sure that longest UD and DU
# sequence starting at each
# index is calculated
for i in range(N):
tmp = f(i, 1, A, dp, N)
tmp = f(i, 2, A, dp, N)
# Assume the answer to be -1
# This value will only increase
ans = -1
for i in range(N):
# y is the length of the longest
# UD sequence starting at i
y = dp[i][1]
if (i + y) >= N:
ans = max(ans, dp[i][1] + 1)
# If length is even then add an integer
# and then a DU sequence starting at i + y
elif y % 2 == 0:
ans = max(ans, dp[i][1] + 1 + dp[i + y][2])
# If length is odd then add an integer
# and then a UD sequence starting at i + y
elif y % 2 == 1:
ans = max(ans, dp[i][1] + 1 + dp[i + y][1])
return ans
# Driver Code
if __name__ == "__main__":
A = [1, 10, 3, 20, 25, 24]
n = len(A)
print(maxLenSeq(A, n))
# This code is contributed by
# sanjeev2552
C#
// C# implementation of the approach
using System;
class GFG
{
// Function to recursively fill the dp array
static int f(int i, int state, int []A,
int [,]dp, int N)
{
if (i >= N)
return 0;
// If f(i, state) is already calculated
// then return the value
else if (dp[i, state] != -1)
{
return dp[i, state];
}
// Calculate f(i, state) according to the
// recurrence relation and store in dp[,]
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 that calls the resucrsive function to
// fill the dp array and then returns the result
static int maxLenSeq(int []A, int N)
{
int i, j, tmp, y, ans;
// dp[,] array for storing result
// of f(i, 1) and f(1, 2)
int [,]dp = new int[1000, 3];
// Populating the array dp[] with -1
for(i = 0; i < 1000; i++)
for(j = 0; j < 3; j++)
dp[i, j] = -1;
// Make sure that longest UD and DU
// sequence starting at each
// index is calculated
for (i = 0; i < N; i++)
{
tmp = f(i, 1, A, dp, N);
tmp = f(i, 2, A, dp, N);
}
// Assume the answer to be -1
// This value will only increase
ans = -1;
for (i = 0; i < N; i++)
{
// y is the length of the longest
// UD sequence starting at i
y = dp[i, 1];
if (i + y >= N)
ans = Math.Max(ans, dp[i, 1] + 1);
// If length is even then add an integer
// and then a DU sequence starting at i + y
else if (y % 2 == 0)
{
ans = Math.Max(ans, dp[i, 1] + 1 +
dp[i + y, 2]);
}
// If length is odd then add an integer
// and then a UD sequence starting at i + y
else if (y % 2 == 1)
{
ans = Math.Max(ans, dp[i, 1] + 1 +
dp[i + y, 1]);
}
}
return ans;
}
// Driver code
public static void Main (String[] args)
{
int []A = { 1, 10, 3, 20, 25, 24 };
int n = A.Length;
Console.WriteLine(maxLenSeq(A, n));
}
}
// This code is contributed by 29AjayKumar
7
时间复杂度: O(n)
空间复杂度: O(n)