Find a sorted subsequence of size 3 in linear time

Given an array of n integers, find the 3 elements such that a[i] < a[j] < a[k] and i < j < k in 0(n) time. If there are multiple such triplets, then print any one of them.

Examples:

```Input:  arr[] = {12, 11, 10, 5, 6, 2, 30}
Output: 5, 6, 30

Input:  arr[] = {1, 2, 3, 4}
Output: 1, 2, 3 OR 1, 2, 4 OR 2, 3, 4

Input:  arr[] = {4, 3, 2, 1}
Output: No such triplet
```

Source: Amazon Interview Question

Hint: Use Auxiliary Space

Solution:
1) Create an auxiliary array smaller[0..n-1]. smaller[i] should store the index of a number which is smaller than arr[i] and is on left side of arr[i]. smaller[i] should contain -1 if there is no such element.
2) Create another auxiliary array greater[0..n-1]. greater[i] should store the index of a number which is greater than arr[i] and is on right side of arr[i]. greater[i] should contain -1 if there is no such element.
3) Finally traverse both smaller[] and greater[] and find the index i for which both smaller[i] and greater[i] are not -1.

C/C++

```// C/C++ program to find a sorted subsequence of size 3
#include<stdio.h>

// A function to fund a sorted subsequence of size 3
void find3Numbers(int arr[], int n)
{
int max = n-1; //Index of maximum element from right side
int min = 0; //Index of minimum element from left side
int i;

// Create an array that will store index of a smaller
// element on left side. If there is no smaller element
// on left side, then smaller[i] will be -1.
int *smaller = new int[n];
smaller[0] = -1;  // first entry will always be -1
for (i = 1; i < n; i++)
{
if (arr[i] <= arr[min])
{
min = i;
smaller[i] = -1;
}
else
smaller[i] = min;
}

// Create another array that will store index of a
// greater element on right side. If there is no greater
// element on right side, then greater[i] will be -1.
int *greater = new int[n];
greater[n-1] = -1;  // last entry will always be -1
for (i = n-2; i >= 0; i--)
{
if (arr[i] >= arr[max])
{
max = i;
greater[i] = -1;
}
else
greater[i] = max;
}

// Now find a number which has both a greater number on
// right side and smaller number on left side
for (i = 0; i < n; i++)
{
if (smaller[i] != -1 && greater[i] != -1)
{
printf("%d %d %d", arr[smaller[i]],
arr[i], arr[greater[i]]);
return;
}
}

// If we reach number, then there are no such 3 numbers
printf("No such triplet found");

// Free the dynamically alloced memory to avoid memory leak
delete [] smaller;
delete [] greater;

return;
}

// Driver program to test above function
int main()
{
int arr[] = {12, 11, 10, 5, 6, 2, 30};
int n = sizeof(arr)/sizeof(arr[0]);
find3Numbers(arr, n);
return 0;
}
```

Java

```// Java program to find a sorted subsequence of size 3
import java.io.*;

class SortedSubsequence
{
// A function to find a sorted subsequence of size 3
static void find3Numbers(int arr[])
{
int n = arr.length;
int max = n-1; //Index of maximum element from right side
int min = 0; //Index of minimum element from left side
int i;

// Create an array that will store index of a smaller
// element on left side. If there is no smaller element
// on left side, then smaller[i] will be -1.
int[] smaller = new int[n];
smaller[0] = -1;  // first entry will always be -1
for (i = 1; i < n; i++)
{
if (arr[i] <= arr[min])
{
min = i;
smaller[i] = -1;
}
else
smaller[i] = min;
}

// Create another array that will store index of a
// greater element on right side. If there is no greater
// element on right side, then greater[i] will be -1.
int[] greater = new int[n];
greater[n-1] = -1;  // last entry will always be -1
for (i = n-2; i >= 0; i--)
{
if (arr[i] >= arr[max])
{
max = i;
greater[i] = -1;
}
else
greater[i] = max;
}

// Now find a number which has both a greater number
// on right side and smaller number on left side
for (i = 0; i < n; i++)
{
if (smaller[i] != -1 && greater[i] != -1)
{
System.out.print(arr[smaller[i]]+" "+
arr[i]+" "+ arr[greater[i]]);
return;
}
}

// If we reach number, then there are no such 3 numbers
System.out.println("No such triplet found");
return;
}

public static void main (String[] args)
{
int arr[] = {12, 11, 10, 5, 6, 2, 30};
find3Numbers(arr);
}
}
/* This code is contributed by Devesh Agrawal*/
```

Python

```# Pythion program to fund a sorted subsequence of size 3

def find3numbers(arr):
n = len(arr)
max = n-1 # Index of maximum element from right side
min = 0 # Index of minimum element from left side

# Create an array that will store index of a smaller
# element on left side. If there is no smaller element
# on left side, then smaller[i] will be -1.
smaller = [0]*10000
smaller[0] = -1
for i in range(1,n):
if (arr[i] <= arr[min]):
min = i
smaller[i] = -1
else:
smaller[i] = min

# Create another array that will store index of a
# greater element on right side. If there is no greater
# element on right side, then greater[i] will be -1.
greater = [0]*10000
greater[n-1] = -1

for i in range(n-2,-1,-1):
if (arr[i] >= arr[max]):
max = i
greater[i] = -1

else:
greater[i] = max

# Now find a number which has both a greater number on
# right side and smaller number on left side
for i in range(0,n):
if smaller[i] != -1 and greater[i] != -1:
print arr[smaller[i]], arr[i], arr[greater[i]]
return

# If we reach here, then there are no such 3 numbers
print "No triplet found"
return

# Driver function to test above function
arr = [12, 11, 10, 5, 6, 2, 30]
find3numbers(arr)

# This code is contributed by Devesh Agrawal
```

Output:

`5 6 30 `

Time Complexity: O(n)
Auxliary Space: O(n)

Exercise:
1. Find a subsequence of size 3 such that arr[i] < arr[j] > arr[k].
2. Find a sorted subsequence of size 4 in linear time

Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above

Company Wise Coding Practice    Topic Wise Coding Practice

Writing code in comment? Please use code.geeksforgeeks.org, generate link and share the link here.

• newCoder3006

In the above written code of @geeksforgeeks:disqus, If arr[]={1, 2, 3, 4} then how will you get {2,3,4} as the output. Pls explain.

• tushar

this code only prints single sequence if it is possible. it doesnt print all the sequences…
to print all the sequences..i dont think its possible to do in O(N)

• xxmajia

for finding any length of sequence, we can just sort the array using O(nlgn) time based on the INDEX, then just run a LIS on it

• tushar

if u sort then order of array will be disturbed which was not supposed to be disturbed

• Sumit Monga

for doing it for 4 numbers , i < j < k < l such that arr[i] < arr[j] < arr[k] < arr[l],we can find smaller for j and greater for k and then between iterate for j and k in between using a list(serving purpose of a stack),see the code if you can understand it:

void find4Numbers(int arr[], int n)

{

int max = n-1; //Index of maximum element from right side for k

int min = 0; //Index of minimum element from left side for j

int i;

// Create an array that will store index of a smaller

// element on left side. If there is no smaller element

// on left side, then smaller[i] will be -1.

int *smaller = new int[n];

smaller[0] = -1; // first entry will always be -1

for (i = 1; i < n; i++)

{

if (arr[i] = 0; i–)

{

if (arr[i] >= arr[max])

{

max = i;

greater[i] = -1;

}

else

greater[i] = max;

}

// Now find a number which has both a greater number on

// right side and smaller number on left side

//now preprocessing the k part from the back

listl;

for(i = n-2; i >= 1; i–) // k can be atmost n-2 and minimum 2, 1 also included

//as j can start from 1.

{

if(greater[i] == -1) //ignore this element

continue;

if(!l.empty())

{

while(!l.empty() && arr[i] > arr[l.front()])

l.pop_front();

if(!l.empty() && smaller[i] != -1)

printf(“n An example: %d %d %d %d”,arr[smaller[i]],arr[i],arr[l.front()],arr[greater[l.front()]]);

}

l.push_front(i);

}

// Free the dynamically alloced memory to avoid memory leak

delete [] smaller;

delete [] greater;

}

`

• Sumit Monga

for doing it for 4 numbers , i < j < k < l such that arr[i] < arr[j] < arr[k] < arr[l],we can find smaller for j and greater for k and then between iterate for j and k in between using a list(serving purpose of a stack),see the code if you can understand it:

void find4Numbers(int arr[], int n)

{

int max = n-1; //Index of maximum element from right side for k

int min = 0; //Index of minimum element from left side for j

int i;

// Create an array that will store index of a smaller

// element on left side. If there is no smaller element

// on left side, then smaller[i] will be -1.

int *smaller = new int[n];

smaller[0] = -1; // first entry will always be -1

for (i = 1; i < n; i++)

{

if (arr[i] = 0; i–)

{

if (arr[i] >= arr[max])

{

max = i;

greater[i] = -1;

}

else

greater[i] = max;

}

// Now find a number which has both a greater number on

// right side and smaller number on left side

//now preprocessing the k part from the back

listl;

//list::iterator it;

for(i = n-2; i >= 1; i–) // k can be atmost n-2 and minimum 2, 1 also included

//as j can start from 1.

{

if(greater[i] == -1) //ignore this element

continue;

if(!l.empty())

{

while(!l.empty() && arr[i] > arr[l.front()])

l.pop_front();

if(!l.empty() && smaller[i] != -1)

printf(“n An example: %d %d %d %d”,arr[smaller[i]],arr[i],arr[l.front()],arr[greater[l.front()]]);

}

l.push_front(i);

}

// Free the dynamically alloced memory to avoid memory leak

delete [] smaller;

delete [] greater;

}

`

• asunel

Can be done using only one extra array !!!

• nishant08
``` ```
plz tell me if there is a problem
#include<stdio.h>
main()
{
int arr[10],i,j=0,n,t[3];
printf("enter no. of elements- ");
scanf("%d", &n);
for(i=0;i<n;i++)
{
printf("enter data- ");
scanf("%d", &arr[i]);
}
for(i=0;i<n;i++)
{
if(j==0)
t[j]=arr[i];

if(arr[i]<arr[i+1])
{
j++;
t[j]=arr[i+1];
if(j==2)
{
for(i=0;i<=2;i++)
printf("%d ", t[i]);
break;
}
}
else  if(i==n-2)
break;
}
}

``` ```
• aspire

I have a solution with O(n) time complexity and O(1) space.
Please correct me if i am wrong.

``` ```
#include<stdio.h>

int find3Size(int a[],int n)
{
int mn=0,mx=n-1,i=1,j=n-2;
if(n<3)
return -1;

while(j>=i)
{
if(a[j]>=a[mx])
mx=j--;
else
j--;
if(a[i]<=a[mn])
mn=i++;
else
i++;

if(a[i]>a[mn]&&a[i]<a[mx])
{
printf("%d %d %d\n",a[mn],a[i],a[mx]);
return 1;
}
else if(a[j]>a[mn]&&a[j]<a[mx])
{
printf("%d %d %d\n",a[mn],a[j],a[mx]);
return 1;
}
}
return 0;
}

int main()
{
int a[]={4, 3, 2, 1},n;
n=sizeof(a)/sizeof(a[0]);
if(find3Size(a,n))
printf("Triplet exists\n");
else
printf(" NO Triplet exists\n");
return 0;
}

``` ```

This runs for all the above test cases and some additional test cases that i checked.

• Sourabh

Yes you are missing Half of the range to check.

``` ```
/* Paste your code here (You may delete these lines if not writing code) */
``` ```
• skulldude

In the above code, I think it is not necessary to check whether the first and last elements have smaller and larger elements as it will always be -1.

Below is the code to solve the problem.

``` ```

// minLeft[i] - Minimum element from a[0] to a[i]
// maxRight[i] - Maximum element from a[len-1] to a[i]

void find3Numbers(int a[],int len){
if(!a || len<=2){
printf("Invalid\n");
return;
}

int *minLeft=new int[len],*maxRight=new int[len];
minLeft[0]=a[0],maxLeft[len-1]=a[len-1];

for(int i=1;i<len;++i){
minLeft[i]=min(minLeft[i-1],a[i]);
maxRight[len-i-1]=max(maxRight[len-i],a[len-i-1]);
}

for(int i=1;i<len-1;++i){
if(minLeft[i-1]<a[i] && a[i]<maxRight[i+1]){
// we have found the solution
printf("%d %d %d\n",minLeft[i-1],a[i],maxRight[i+1]);
return;
}
}

printf("No such sequence found\n");
return;
}

``` ```

Please comment, if you find any bugs in the code.

-Balasubramanian.N

• aspire

I have a solution with O(n) time complexity and O(1) space.
Please correct me if i am wrong.

``` ```
#include<stdio.h>

int find3Size(int a[],int n)
{
int mn=0,mx=n-1,i=1,j=n-2;
if(n<3)
return -1;

while(j>=i)
{
if(a[j]>=a[mx])
mx=j--;
else
j--;
if(a[i]<=a[mn])
mn=i++;
else
i++;

if(a[i]>a[mn]&&a[i]<a[mx])
{
printf("%d %d %d\n",a[mn],a[i],a[mx]);
return 1;
}
else if(a[j]>a[mn]&&a[j]<a[mx])
{
printf("%d %d %d\n",a[mn],a[j],a[mx]);
return 1;
}
}
return 0;
}

int main()
{
int a[]={4, 3, 2, 1},n;
n=sizeof(a)/sizeof(a[0]);
if(find3Size(a,n))
printf("Triplet exists\n");
else
printf(" NO Triplet exists\n");
return 0;
}

``` ```

This runs for all the above test cases and some additional test cases that i checked.

• Ganesh

You can find java code here:

[sourcecode language="JAVA"]
/**
* Given an array of n integers, find the 3 elements such that a[i] < a[j] < a[k] and i < j < k in 0(n) time.
* If there are multiple such triplets, then print any one of them.
* Example: Input: arr[] = {12, 11, 10, 5, 6, 2, 30} Output: 5, 6, 30
* @author GAPIITD
*
*/
public class SortedSubsequenceOfSize3 {

public static void main(String[] args) {
int arr[] = {12, 11, 10, 5, 6, 2, 30};
int small[] = new int[arr.length];
int large[] = new int[arr.length];
small[0] = large[arr.length – 1] = -1;
int min = arr[0], max = arr[arr.length – 1];
// Create an array that will store index of a smaller element on left side.
// If there is no smaller element on left side, then smaller[i] will be -1.
for (int i = 1; i < arr.length; i++) {
if (arr[i] < min) {
small[i] = -1;
min = arr[i];
}
else small[i] = min;
}
// Create another array that will store index of a greater element on right side.
// If there is no greater element on right side, then greater[i] will be -1.
for (int i = arr.length – 2; i > 0; i–) {
if (arr[i] > max) {
large[i] = -1;
max = arr[i];
}
else large[i] = max;
}
// Now find a number which has both a greater number on right side and smaller number on left side
for (int i = 0; i < arr.length; i++) {
if (small[i] != -1 && large[i] != -1) {
System.out.println(small[i] + " " + arr[i] + " " + large[i]);
}
}
}
}

• azee

Can’t we user longest increasing subsequence logic for this problem. And using longest subsequence problem we print all subsequences with length more than or equal to 3. In this way we get all combinations of sorted subsequence of size 3. If I am wrong, please let me know where this logic might go wrong.

• Paparao Veeragandham

It will take O(nlogn) time.

``` ```
/* Paste your code here (You may delete these lines if not writing code) */
``` ```
• Paparao Veeragandham

Please post solution for sorted sequence of size 4 in linear time

• tushar

it will take O(n2) time

• VikasG

I think this will work. Let me know if you can spot any issues.

``` ```
void printSubSequence3(int array[], int n) {
//error checking
assert( n >= 3 );

int p = -1; // index of min0
int q = -1; // index of min1
int r = -1; // index of min2

for (int i = 1; i < n ; i++) {
//compare i with i - 1
if (array[i] > array[i-1]) { //found increasing subSequence
if ( p == -1 && q == -1) {
//Our new subSequence is array[i-1], array[i], ?
q = i;
p = i - 1;
} else {
assert ( p != -1);
assert ( q != -1);
if (array[i] > array[q]) { // case I
//Our subSequence is array[p], array[q], array[i]
cout << array[p] << "," << array[q] << "," << array[i] << endl;
return;
} else if (array[i] < array[q]) {
if (array[i] > array[p]) { //case 3
//we have new element for q. Our new subSequence is array[p], array[i], ?
q = i;
} else if (array[i] < array[p]) { //case 4
//Our new subSequence is array[i-1], array[i], ?
q = i;
p = i - 1;
}
}
}
}
}
}
``` ```
• Amandeep Gautam

I think that this algorithm will also work. If any mistakes please point out.

// initialize four variables to 0.
int i=0, j=0, k=0, counter=0
//start parsing the array.
while ( a[i] j
if ( a[counter] > a[j] ) {
break;
}
else if ( a[counter] > a[i] && a[counter] < a[j] ) {
j=counter;
if ( k!=0 ) {
i=k;
k=0;
}
}
else if ( (a[counter] < a[i]) || (a[counter]< a[k]) ) {
k=counter;
}

• Amandeep Gautam

The above algorithm is o(n) time and O(1) space.

• ``` ```
// find the first adjacent elements in ascending order and continue find the next adjacent elements
// compare the two pairs of adjacent elements
// A[x] > A[i] => i, x, x + 1
// A[x+1] > A[j] => i, j, x + 1
// set i to x and j to x + 1 and otherwise continue
public void find(int[] A)
{
int i = -1;
int j = -1;
int k = -1;
int x = 0;
int l = A.length;
while(x < l - 2 && A[x+1] <= A[x]) x++;
if(x < l - 2) {
i = x;
j = x + 1;
x++;
while(x < l - 1) {
if(A[x+1] > A[x]) {
if(A[x] > A[i]) {
j = x;
k = x + 1;
break;
} else if(A[x+1] > A[j]) {
k = x + 1;
break;
} else {
i = x;
j = x + 1;
}
}
x++;
}
}
if(-1 < i && i < j && j < k && k < l) System.out.println(String.format("%d %d %d", A[i], A[j], A[k]));

}
``` ```

space complexity O(1)
time complexity O(n)

• Nirdesh

Your soluation will not work for input :

{ 1,12, 11, 2, -2,-5,10 }

where expected result is : 1,2,10 but your program prints nothings.

• nitin gupta iitian
`  `

/* Paste your code here (You may delete these lines if not writing code) */
[@geeksforgeeks
Its very easy dud
it like a maximum and minimum problem

Logic is very simple
actually we have to first find the minimum value .once we encounter minimum value at index i we need to find greater value
greater than previous value
{12, 11, 10, 5, 6, 2, 30,5,3,32,2,40};
first we found minimum value 11 then 10 then 5 (since 6 > 5 )
now we find greater value’s which is greater to previous one
we have 5 now next is 6 next is 30 next is 32 and 40

EASY NA!
I DON’T KNOW WHY YOU NEED TWO ARRAY ?
]

• andrew

this will be wrong in case:

{12, 11, 10, 5, 6, 2, 3, 4}

``` ```
/* Paste your code here (You may delete these lines if not writing code) */
``` ```
• NITIN GUPTA IITIAN

@geeksforgeeks
Its very easy dud
it like a maximum and minimum problem

simplest Logic is
actually we have to first find the minimum value .once we encounter minimum value at index i we need to find greater value
greater than previous value
{12, 11, 10, 5, 6, 2, 30,5,3,32,2,40};
first we found minimum value 11 then 10 then 5 (since 6 > 5 )
now we find greater value’s which is greater to previous one
we have 5 now next is 6 next is 30 next is 32 and 40

EASY NA!

``` ```
/* Paste your code here (You may delete these lines if not writing code) */
``` ```
• lohith
``` ```
import java.util.ArrayList;

public class subsequence3 {

public static int array[] = {5,2,6,3,4};

public static void main(String str[]){

ArrayList<Integer> inn = new ArrayList<Integer>();
for(int i=0;i<array.length;i++){
}

ArrayList<Integer> resu = Subsequence(inn,0);

for(int i=0;i<resu.size();i++){
System.out.println(array[resu.get(i)]);
}

}

private static ArrayList<Integer> Subsequence(ArrayList<Integer> arr,int foundIndex) {

if(foundIndex<3 && arr!=null  && !arr.isEmpty()){

for(int i=0;i<arr.size();i++){
int curr =  array[arr.get(i)];
ArrayList<Integer> temp = new ArrayList<Integer>();
for(int j=i+1;j<arr.size();j++){
if(curr < array[arr.get(j)]){
}
}

ArrayList<Integer> temp1 = Subsequence(temp,foundIndex+1);
if(temp1.size() == (3-(foundIndex+1))){
ArrayList<Integer> answer = new ArrayList<Integer>();

}
}

}

return arr;
}

}

``` ```
• lei

build auxiliary array will be o(n*n); so average it is not o(n)

• ashu

you can build your auxillary array using stack. it will take o(n) time.

``` ```
/* Paste your code here (You may delete these lines if not writing code) */
``` ```
• ashu

you can build auxiliary array using stack in o(n) time.

``` ```
/* Paste your code here (You may delete these lines if not writing code) */
``` ```
• Ashu

I think approach for 4 increasing sorted sub-sequence is same , you need to store indexes of next bigger element of a[i] in greater[i] and last smaller element of a[i] in smaller[i].

then for every index you can check if for index i , (smaller[i]!=-1 and smaller[smaller[i]] != -1 and greater[i]!=-1) or( smaller[i]!=-1 and greater[i]!=-1 and greater[greater[i]])

``` ```
/* Paste your code here (You may delete these lines if not writing code) */
``` ```
• souvik

O(n) time O(1) space for the 3 element problem

``` ```
void find(int x[],int n)
{
int i=0,j=n,k=n,l;
if(n<3)
{
printf("Not enough elements");
return;
}
for(l=1;l<n;l++)
{
if(j==n)
{
if(x[l]>x[i])
j=l;
else
i=l;
}
else
{
if(x[l]>x[j])
{
printf("%d %d %d",i,j,l);
return;
}
else
{
if(k==n)
k=l;
else
{
if(x[l]<=x[k])
k=l;
else
{
i=k;
j=l;
k=n;
}
}
}
}
}
printf("No such subsequence found");
}
``` ```
• anonymous

@souvik
You should always put comments in your code so that one can understand what’s going on inside the code

• Anurag Singh

Exercise 1:
Find a subsequence of size 3 such that arr[i] arr[k]

Here we will calculate two smaller arrays, say smaller1 and smaller2.
smaller1 array will be exactly same as smaller array in solution of original problem (store the index of a smaller number on the left side)
smaller2 will be opposite, it will store the index of a smaller number in right side.

Now traverse smaller1 and smaller2 arrays, find an index i where
smaller1[i] != -1 && smaller2[i] != -1

And then expected output will be:
arr[smaller1[i]], arr[i], arr[smaller2[i]]

Pretty simple. Liked it. We can also have a third auxialiary array which will store the second max or second min(whichever the case maybe) for every index.

``` ```
/* Paste your code here (You may delete these lines if not writing code) */
``` ```
• Anurag Singh

Exercise 2:
Find a sorted subsequence of size 4 in linear time

Here we will calculate greater and smaller arrays as is.
Now if at all, there is an sorted subsequence of size 4, then there will be two different index i and j (i < j) such that
smaller[i] != -1 && greater[i] != -1, also
smaller[j] != -1 && greater[j] != -1

i and j can be found by traversing forward and backward in same loop. and then 4 sorted subsequences will be
arr[smaller[i]], arr[i], arr[j], arr[greater[j]]

if no such i and j found, then there is no sorted subsequence of size 4.

• Game

Apparently you have not free’d the memory you new’d.

• geeksforgeeks

@game: Thanks for pointing this out. We have added code to delete dynamically allocated memory. Keep it up!

• Ankush

Any approach in linear time to size 4 increasing sorted sub-sequence problem?

• Ashu

I think approach for 4 increasing sorted sub-sequence is same , you need to store indexes of next bigger element of a[i] in greater[i] and last smaller element of a[i] in smaller[i].

then for every index you can check if for index i , (smaller[i]!=-1 and smaller[smaller[i]] != -1 and greater[i]!=-1) or( smaller[i]!=-1 and greater[i]!=-1 and greater[greater[i]])

``` ```
/* Paste your code here (You may delete these lines if not writing code) */
``` ```
• Ankush

Any approach to the sorted sub-sequence of size 4 problem??

• Nicam

O(n) solution with O(1) space

``` ```
public ArrayList<Integer> find3Numbers (int[] a) {
if (a == null || a.length < 3) return null;
int i = -1, j = -1;
ArrayList<Integer> ans = new ArrayList<Integer>(3);

for (int k = 1; k < a.length; ++k) {
if (i != -1 && j != -1 && a[k] > a[j]) {
return ans;
} else if (a[k] > a[k-1]) {
if (i != -1 && j != -1) {
i = (a[k-1] < a[i]) ? k-1 : i;
j = (a[k] < a[j]) ? k : j;
} else {
i = k-1;
j = k;
}
}
}

return ans;
}
``` ```
• Nicam

Corrected one logic bug, the code wasn’t working on {5,2,6,3,4}, now should be okay

``` ```
public ArrayList<Integer> find3Numbers (int[] a) {
if (a == null || a.length < 3) return null;
int i = -1, j = -1;
ArrayList<Integer> ans = new ArrayList<Integer>(3);

for (int k = 1; k < a.length; ++k) {
if (i != -1 && j != -1 && a[k] > a[j]) {
return ans;
} else if (a[k] > a[k-1]) {
if (i != -1 && j != -1) {
i = (a[k-1] < a[i]) ? k-1 : i;
j = (a[k] < a[j]) ? k : j;
} else {
i = k-1;
j = k;
}
} else if (i != -1 && j != -1) {
if (a[k] > a[i] && a[k] < a[j]) j = k;
}
}

return ans;
}
``` ```
• Prem

@Nicam Can u pls explain ur logic?

• Ram

says

simple

• doom

Any ideas for exercise 2: Find a sorted subsequence of size 4 in linear time?

• Hamid

I think your original code is not taking care of “equal to” condition properly. for example, it will print a sequence on following input:
8 8 8 8 8 8 8

I believe that you should <= instead of just < in following statement while filling up smaller array:
if (arr[i] < arr[min])

and similar logic needs to be followed while filling up greater array as well.

• geeksforgeeks

@Hamid:
Thanks for pointing this out. We have changed the condition. Keep it up!

• abc
• anonymous

does not work for..
{12,11,10,5,6,2,3,4}

• manish

This is not working, i think the…solution should contain for arr[] = {1,2,3,4}
output = {1,2,3},{1,3,4},{1,2,4}and {2,3,4}

[sourcecode language="C++"]
#include <cstdio>
#include <iostream>
using namespace std;

void find3Numbers(int arr[],int n);
int main()
{
int arr[] = {1,2,3,4};
int arr1[] = {12,11,10,5,6,2,30};
find3Numbers(arr,sizeof(arr)/sizeof(arr[0]));
find3Numbers(arr1,sizeof(arr1)/sizeof(arr1[0]));
return 0;
}

void find3Numbers(int arr[],int n)
{
int max = n-1;
int min = 0;
int i;
int *smaller = new int[n];
smaller[0] = -1;
for (i = 1; i < n; i++) {
if(arr[i] < arr[min]) {
min = i;
smaller[i] = -1;
} else {
smaller[i] = min;
}
}
int *greater = new int[n];
greater[n-1] = -1;
for(i = n-2; i>=0; i–) {
if(arr[i] > arr[max]) {
max = i;
greater[i] = -1;
} else {
greater[i] = max;
}
}
for (i = 0; i < n; i++) {
if(smaller[i] != -1 && greater[i] != -1) {
printf("%d %d %d\n",arr[smaller[i]],arr[i],arr[greater[i]]);

}
}
return;
}

• GeeksforGeeks

@manish: Please take a closer look at the problem statement. It says print any of the triplets. The program given in post prints {1, 2, 4} for your input which looks correct.

• @geeksforgeeks

thank you…i got it

• Saravan

Solutions to find first occurrence in passed array!

``` ```
public class FindTriplets {
public static void main(String[] args) {
int [] arr1 = {12, 11, 10, 5, 6, 2, 30};
int [] arr2 = {1, 2, 3, 4};
int [] arr3 = {4, 3, 2, 1};
solution1(arr1);
solution1(arr2);
solution1(arr3);

solution2(arr1);
solution2(arr2);
solution2(arr3);
}

private static void solution2(int [] arr) {
int i = 0;
int j = i + 1;
int counter = 0;
boolean found = false;
for (;counter < arr.length - 1;counter ++) {
if (arr[i] < arr[j]) {
found = true;
break;
} else {
i = j;
j = j + 1;
}
}

int k = j + 1;
if (found) {
for (;counter < arr.length - 1;counter ++) {
if (arr[j] < arr[k]) {
found = true;
break;
} else {
k++;
found = false;
}
}
}

if (found) {
System.out.println("Positions are: " + i + ", " + j + ", " + k);
System.out.println("Values are: " + arr[i] + ", " + arr[j] + ", " + arr[k]);
} else {
System.out.println("No expected sequence found!");
}
}

private static void solution1(int [] arr) {
int i = 0;
int j = i + 1;
int k = j + 1;
int counter = 0;
boolean iLessJDone = false;
boolean jLessKDone = false;
for (;counter < arr.length - 2;counter ++) {
if (arr[i] < arr[j]) {
k = j + 1;
iLessJDone = true;
} else if (!iLessJDone) {
i = j;
j = j + 1;
}

if (iLessJDone && (arr[j] < arr[k])) {
jLessKDone = true;
break;
} else if (!jLessKDone) {
k++;
}
}

if (k >= arr.length) {
System.out.println("No expected sequence found!");
} else {
System.out.println("Positions are: " + i + ", " + j + ", " + k);
System.out.println("Values are: " + arr[i] + ", " + arr[j] + ", " + arr[k]);
}
}
}
``` ```
• deepesh

your code doesnot work for { 10,12,1,2,3};
any sequence which is first find element in increasing order arr[i] < arr[j] but after that it doesnt not find k which is greater then arr[i] and arr[j] but their is still a seqeunce of increasing order

[sourcecode language="C"]
/* Paste your code here (You may delete these lines if not writing code) */

• Pramod

I thought of converting the list in binary tree, then realize the objective is to find the triplets. Therefore changed logic to print all triplets found in the given array.

public class FindTripplets {

// A function to find a sorted subsequence of size 3
public void findAnyOneTriplet(int arr[], int n)
{

List triplets = new ArrayList();
Triplet l = new Triplet();

for (int i =1 ; i < arr.length; i++){

int cnt= triplets.size();
int value = arr[i];
//get the node from array
for (int c= 0; c <cnt; c++){

Triplet triplet =triplets.get(c);

//check if the current value can be added
if(triplet.getCount() < 3 && triplet.getCurrentValue() < value){
}

if(! isExist(triplets, value)){
//not , then create triplet and add to the linked list
Triplet t = new Triplet();
}

}
}

boolean found =false;
for (Triplet triplet : triplets){
if(triplet.getCount() == 3){
triplet.printList();
found = true;
}
}

if(!found) {
// If we reach number, then there are no such 3 numbers
System.out.println("No such triplet found");
}

}

private boolean isExist(List triplets, int value) {
for (Triplet triplet : triplets){
return true;
}
}
return false;
}

private class Triplet{
int count;
Node lastNode;

public Triplet(){

}

public int getCount(){return count;}

}

public int getCurrentValue(){
return lastNode.value;
}

public void addNode(int value){
head = new Node(value);
}else{
Node n = new Node(value);
lastNode.setNext(n);
lastNode = n;
}
++count;
}

public void printList(){
Node n = head;
while(n != null){
System.out.print(n.getValue() + ” ” );
n = n.next;
}
System.out.println();
}

}

private class Node{
int value;
Node next = null;

public Node( int value){
this.value = value;

}

public int getValue(){ return value;}

public Node getNext() {
return next;
}

public void setNext(Node next) {
this.next = next;
}
}

public static void main(String[] args){

int arr[] = {12, 11, 10, 5, 6, 2, 30};
FindTripplets findTripplets = new FindTripplets();
findTripplets.findAnyOneTriplet(arr, arr.length);
arr = new int[]{1,2,3,4};
findTripplets.findAnyOneTriplet(arr, arr.length);
arr = new int[]{4,3,2,1};
findTripplets.findAnyOneTriplet(arr, arr.length);

}

}

• Guddu sharma

Exercise 2
Find three elements as per above approach. After finding check the following two cases:
1.search for an element el,from i+1 to j-1,such that el>ar[p] && elar[p] && el<ar[p] if yes,o/p the numbers

[sourcecode language="C"]
/* Paste your code here (You may delete these lines if not writing code) */

• Camster

Guddu Sharma, Suppose there are multiple triplets and you select the one that cannot be extended to a quartet. The only sure way to select the correct triplet to extend to a quartet is to try all triplets which costs O( n * n ) time. Thank you camster.

``` ```
/* Paste your code here (You may delete these lines if not writing code) */
``` ```
• Nitin

I propose a O(1) space logic for the same.Please point out if there is any mistake in this.
Maintain a stack of size 3.I assume that all the elements of the stack are directly accessible (like using array or something similar)
1) push first element in the stack.iterate through the array.
Following conditions can occur:
a). Element(next) is smaller than the only element in the stack.
-> Pop the stack and push this element.
b). Element is greater than this element.
-> Push this element onto the stack.
C). ( When size of stack is 2 )Element is lesser than the top element but greater than the first (bottom) element of the stack
-> Pop the stack and push this new element.
d). (size of stack is 2)Element is greater than top element.
-> Print the three elements.
e). (size of stack is 2) Element is smaller than the first element.
-> Store the top.Pop all the elements.Push the new element.Now if this situation occurs more than one time, store the minimum of the two such top elements (say MIN2). And if while traversing through the array you find any element greater than this MIN2, then you’ve got those numbers.(Traverse again to find the first number)

In fact stack is not necessary just keeping track of four variables is sufficient.

• Hamid

I do not understand your point e), can you elaborate more with example? I do not think that your code will work on following input (unless i am missing something in point e):

8 10 7 8 6 9

• Gang

The following code is along the line suggested by Nitin, with O(n) time and O(1) space.

``` ```
bool FindSortedTriplet(int const A[], int const N, int& x, int& y, int& z)
{
if (A != nullptr && N > 2)
{
int a = numeric_limits<int>::max();
int b = a;
for (int i = 0; i < N; ++i)
{
if (A[i] > b)
{
z = A[i];
return true;
}
else if (A[i] > a)
{
x = a;
y = b = A[i];
}
else
{
a = A[i];
}
}
}

return false;
}

void testSortedTriplet()
{
{
int a, b, c;
int const H[] = {12, 11, 10, 5, 6, 2, 30};
assert(FindSortedTriplet(H, ARRAY_LENGTH(H), a, b, c));
assert(a == 5);
assert(b == 6);
assert(c == 30);
}

{
int a, b, c;
int const H[] = {1, 2, 3, 4};
assert(FindSortedTriplet(H, ARRAY_LENGTH(H), a, b, c));
assert(a == 1);
assert(b == 2);
assert(c == 3);
}

{
int a, b, c;
int const H[] = {4, 3, 2, 1};
assert(!FindSortedTriplet(H, ARRAY_LENGTH(H), a, b, c));
}

{
int a, b, c;
int const H[] = {8, 10, 7, 8, 6, 9};
assert(FindSortedTriplet(H, ARRAY_LENGTH(H), a, b, c));
assert(a == 7);
assert(b == 8);
assert(c == 9);
}
}
``` ```
• Nitin

I’ll explain you using the example you suggested.

8 : push to stack; stack : 8 _ _
10: push stack : 8 10 _
7 : according to point e, pop all elements
and store max element i.e. 10 stack : 7 _ _
8 : stack : 7 8 _
6 : store min of 10,8 i.e. 8 stack : 6 _ _
9 : now 9 is > 8 i.e. two elements must’ve come before 9 that are less than 9, hence the triplet is 7 8 9

• Ashu

But where did you store “7” . you removed already 7 from the stack. so how did you know in last triplet is 7 8 9 ???

``` ```
/* Paste your code here (You may delete these lines if not writing code) */
``` ```
• atul

just a typo mistake …. you can correct it if you want…
In second part where greater[] is calculated..

// Create another array that will store the index of a
// greater element on left(right) side. If there is no smaller(greater)
// element on left(right) side, then smaller[i](greater[i]) will be -1.

``` ```
/* Paste your code here (You may delete these lines if not writing code) */
``` ```
• GeeksforGeeks

@atul: Thanks for pointing this out. We have corrected the typo. We always want to correct our errors/mstakes.

• raja

Exercise 1. Two smaller arrays are needed: one from left side and other from right side.

• raja

sweet and simple. G4G continue to rock