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
Explanation: As 5 < 6 < 30, and they 
appear in the same sequence in the array 

Input: arr[] = {1, 2, 3, 4}
Output: 1, 2, 3 OR 1, 2, 4 OR 2, 3, 4
Explanation: As the array is sorted, for every i, j, k,
where i < j < k, arr[i] < arr[j] < arr[k] 

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

Hint: Use Auxiliary Space.



Solution: So, the main motive is to find an element which has an element smaller than itself on the left side of the array and an element greater than itself on the right side of the array, if there is any such element then there exists a triplet that satisfies the criteria.

Approach: This can be solved in a very simple way. To find an element which has an element smaller than itself on its left side of the array, check if that element is the smallest element while traversing the array from starting index i.e., (0), and to check if there is an element greater than itself on its right side of the array check whether that element is the largest element while traversing from the end of the array i.e., (n-1). If the element is not the smallest element from 0 to that index then it has an element smaller than itself on it left side, and similarly if the element is not the largest element from that index to the last index then there is a larger element on its right side.

Algorithm

  1. Create an auxiliary array smaller[0..n-1]. smaller[i] stores the index of a number which is smaller than arr[i] and is on left side. The array contains -1 if there is no such element.
  2. Create another auxiliary array greater[0..n-1]. greater[i] stores the index of a number which is greater than arr[i] and is on right side of arr[i]. The array contains -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 equal to -1.

C++

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ program to find a sorted
// sub-sequence of size 3
#include <bits/stdc++.h>
using namespace std;
  
// A function to fund a sorted
// sub-sequence of size 3
void find3Numbers(int arr[], int n)
{
    // Index of maximum element
    // from right side
    int max = n - 1;
  
    // Index of minimum element
    // from left side
    int min = 0;
    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];
  
    // first entry will always be -1
    smaller[0] = -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];
  
    // last entry will always be -1
    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;
    }
  
    // 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) {
            cout << arr[smaller[i]]
                 << " " << arr[i] << " "
                 << arr[greater[i]];
            return;
        }
    }
  
    // If we reach number, then there are
    // no such 3 numbers
    cout << "No such triplet found";
  
    // Free the dynamically allocated memory
    // to avoid memory leak
    delete[] smaller;
    delete[] greater;
  
    return;
}
  
// Driver code
int main()
{
    int arr[] = { 12, 11, 10, 5, 6, 2, 30 };
    int n = sizeof(arr) / sizeof(arr[0]);
    find3Numbers(arr, n);
    return 0;
    a greater number on
}
  
// This is code is contributed by rathbhupendra

chevron_right


C

filter_none

edit
close

play_arrow

link
brightness_4
code

// C program to find a sorted
// sub-sequence of size 3
#include <stdio.h>
  
// A function to fund a sorted
// sub-sequence of size 3
void find3Numbers(int arr[], int n)
{
    // Index of maximum element
    // from right side
    int max = n - 1;
  
    // Index of minimum element
    // from left side
    int min = 0;
    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];
  
    // first entry will always be -1
    smaller[0] = -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];
  
    // last entry will always be -1
    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;
    }
  
    // 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 allocated 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;
}

chevron_right


Java

filter_none

edit
close

play_arrow

link
brightness_4
code

// Java program to find a sorted
// sub-sequence of size 3
import java.io.*;
  
class SortedSubsequence {
    // A function to find a sorted
    // sub-sequence of size 3
    static void find3Numbers(int arr[])
    {
        int n = arr.length;
  
        // Index of maximum element
        // from right side
        int max = n - 1;
  
        // Index of minimum element
        // from left side
        int min = 0;
        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];
  
        // first entry will always be -1
        smaller[0] = -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];
  
        // last entry will always be -1
        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;
        }
  
        // Now find a number which has
        // both 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*/

chevron_right


Python

filter_none

edit
close

play_arrow

link
brightness_4
code

# Python program to fund a sorted
# sub-sequence of size 3
  
def find3numbers(arr):
    n = len(arr)
  
# Index of maximum element from right side
    max = n-1
  
# Index of minimum element from left side 
    min = 0
  
    # 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

chevron_right


C#

filter_none

edit
close

play_arrow

link
brightness_4
code

// C# program to find a sorted
// subsequence of size 3
using System;
  
class SortedSubsequence {
  
    // A function to find a sorted
    // subsequence of size 3
    static void find3Numbers(int[] arr)
    {
        int n = arr.Length;
  
        // Index of maximum element from right side
        int max = n - 1;
  
        // Index of minimum element from left side
        int min = 0;
        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];
  
        // first entry will always be -1
        smaller[0] = -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];
  
        // last entry will always be -1
        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;
        }
  
        // 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) {
                Console.Write(
                    arr[smaller[i]] + " " + arr[i]
                    + " " + arr[greater[i]]);
                return;
            }
        }
  
        // If we reach number, then there
        // are no such 3 numbers
        Console.Write("No such triplet found");
        return;
    }
  
    // Driver code
    public static void Main()
    {
        int[] arr = { 12, 11, 10, 5, 6, 2, 30 };
        find3Numbers(arr);
    }
}
  
/* This code is contributed by vt_m*/

chevron_right


PHP

filter_none

edit
close

play_arrow

link
brightness_4
code

<?php 
// PHP program to find a sorted 
// subsequence of size 3
  
// A function to fund a sorted
// subsequence of size 3
function find3Numbers(&$arr, $n)
{
    // Index of maximum element from right side
    $max = $n - 1;
  
    // Index of minimum element from left side 
    $min = 0; 
      
    // 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 = array_fill(0, $n, NULL);
    $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.
    $greater = array_fill(0, $n, NULL);
      
    // last entry will always be -1
    $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;
    }
      
    // 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)
        {
            echo $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");
      
    return;
}
  
// Driver Code
$arr = array(12, 11, 10, 5, 6, 2, 30);
$n = sizeof($arr);
find3Numbers($arr, $n);
  
// This code is contributed 
// by ChitraNayal
?>

chevron_right


Output:

5 6 30

Complexity Analysis

  • Time Complexity: O(n). As the array is traveled only once and there are no nested loops, the time complexity will be in the order of n.
  • Auxiliary Space: O(n). Since two extra array is needed to store the index of previous lesser element and next greater element so the space required will also be in the order of n

Reference: How to find 3 numbers in increasing order and increasing indices in an array in linear time

Exercise:

  1. Find a sub-sequence of size 3 such that arr[i] arr[k].
  2. Find a sorted sub-sequence 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




My Personal Notes arrow_drop_up