arya
arya

Reputation: 575

Longest subsequence that first increases then decreases

I am trying to solve the following question :


A sequence in which the value of elements first decrease and then increase is called V- Sequence. In a valid V-Sequence there should be at least one element in the decreasing and at least one element in the increasing arm.

For example, "5 3 1 9 17 23" is a valid V-Sequence having two elements in the decreasing arm namely 5 and 3, and 3 elements in the increasing arm namely 9, 17 and 23 . But none of the sequence "6 4 2" or "8 10 15" are V-Sequence since "6 4 2" has no element in the increasing part while "8 10 15" has no element in the decreasing part.

A sub-sequence of a sequence is obtained by deleting zero or more elements from the sequence. For example definition "7", "2 10", "8 2 7 6", "8 2 7 10 6" etc are valid sub-sequences of "8 2 7 10 6"

Given a sequence of N numbers find its longest sub-sequence which is a V-Sequence.


I currently have an O( n^2 ) solution wherein I first initialize an array ( m[] ) such that each m[i] contains the longest increasing sequences STARTING at 'i' within the array.

Similarly, I initialize another array ( d[] ), such that each d[i] contains the longest decreasing sequence ENDING at that point.

Both of these operations take O( n^2 )

I now go through these arrays and choose the maximum value of m[i] + d[i] -1 , such that required conditions are satisfied.

What I want to know is - Is there an O( n lg n ) solution ?? Because my solution does not run within required time limits. Thank you :)

CODE :

#include<cstdio>
#include<algorithm>

using namespace std;



int m[ 200000 ];
int d[200000 ];
int n;
int arr[200000 ];

void LIS()
{
    m[ n-1 ] = 1;

    int maxvPos = -1;
    int maxv = -1;

    for( int i=n-2; i>=0; i-- )
    {
        maxv = -1;
        for( int j=i+1; j<n; j++ )
        {
            if( ( m[j]+1 > maxv ) && ( arr[i] < arr[j]) )
            {
                maxv = m[j]+1;
                maxvPos = j;
            }


        }
        if( maxv>0 )
            {
                m[i] = maxv;
            }

            else
                m[i ] = 1;
    }

 }

void LDS()
{
      d[0] = 1;

    int maxv = -1;
    int maxvPos = -1;

    for( int i=1; i<n; i++ )
    {
        maxv = -1;
        for( int j=i-1; j>=0; j-- )
        {
            if( ( d[j]+1 > maxv) && arr[j]>arr[i] )
            {
                maxv = d[j]+1;
                maxvPos = j;
            }
        }

        if( maxv>0 )
            d[i] = maxv;

        else
            d[i]=1;
    }

}

int solve()
{
    LIS();
    LDS();

    int maxv = 0;
    int curr = 0;

    for( int i=0; i<n; i++ )
    {
        curr = d[i] + m[i] -1 ;

        if( ( d[i]>0) && (m[i]>0 ))
        {
            if( curr != 1 )
            maxv = max( curr, maxv );
        }

    }

    return maxv;

}

/*    static void printArr( int[] a )
{
    for( int i : a )
        System.out.print( i + " ");

    System.out.println();
} */


int main()
{
    scanf( "%d", &n );

    for( int i=0; i<n; i++ )
    {
        scanf("%d", &arr[i] );
    }   

    printf("%d\n", solve() );
    return 0;

}

Upvotes: 5

Views: 2891

Answers (4)

Ishmeet Singh
Ishmeet Singh

Reputation: 139

Construct array inc[i] where inc[i] stores Longest Increasing subsequence ending with A[i]. Construct array dec[i] where dec[i] stores Longest Decreasing subsequence ending with A[i].

then find the maximum value of (inc[i] + dec[i] - 1)

Upvotes: 0

simplest_coder
simplest_coder

Reputation: 51

This one is a O(n) solution. Checked it on basic examples.
Let me know if it has any problem or if it does not work for any particular case.

CODE :

#include<stdio.h>
int max(int a,int b)
{
return (a >= b ? a : b);
}
int main()
{
    int i,j,n;
    scanf("%d",&n);
    int A[200022];
    int dec[200022]={0};
    int V[200022]={0};
    int state[200022]={0};
    for(i=0;i<n;i++)
    {
      scanf("%d",&A[i]);
    }
    if(A[0] > A[1])
        state[0]=1;
    for(i=1;i<n;i++)
    {
        j=i-1;
            if(A[i] < A[j])
            {    
                dec[i]=max(dec[i],dec[j]+1);
                V[i]=max(V[i],V[j]);
                state[i]=1;
            }    
            else if(A[i] == A[j])
            {    
                dec[i]=dec[j];
                V[i]=V[j];
                state[i]=state[j];
            }
            else
            {
                if(state[j]==1)
                {
                    dec[i]=dec[i];
                    V[i]=max(V[i],dec[j]+1);
                    V[i]=max(V[i],V[j]+1);
                    state[i]=1;
                }
                else
                {
                    dec[i]=dec[i];
                    V[i]=max(V[i],V[j]);
                }
            }

//  printf("%d %d\n",dec[i],V[i]);
}
    if(V[n-1] == 0)
        printf("0\n");
    else
        printf("%d\n",V[n-1]+1);
 }

Upvotes: 0

blueshift
blueshift

Reputation: 6891

Edit: Oh, this answer is wrong. I missed the part about being able to delete elements to make longer conforming sequences. Still, for entertainment, here's a solution for the simple case where you don't get to delete elements:

I can think of an O(n) solution:

Walk the list once. Maintain some variables:

  • start of longest v-sequence seen
  • length of longest v-sequence seen
  • start of current v-sequence
  • current scan position
  • current scan state (ascending or descending)

Initialise both start pointers to the first element, the longest to zero, and the scan state to descending.

  1. Walk the list so long as numbers are descending and in the descending state.
  2. When an increasing number is encountered, change to ascending state and keep walking
  3. When the next decreasing number is encoutered, this is the end of a v-sequence.
  4. Compare with longest currently encountered v-sequence and update that if this one is longer.
  5. Reset start of current v-sequence and scan state to descending
  6. Walk the next sequence
  7. At end of array, return start and length of longest sequence.

Upvotes: 0

Sabbir Yousuf Sanny
Sabbir Yousuf Sanny

Reputation: 594

There are O(NlgK) algorithm for Longest Increasing Subsequence problem, where K is the LIS length. You can check Wikipedia for a description of the algorithm. LightOJ also has a nice tutorial (this might require login).

Upvotes: 5

Related Questions