Given an array arr[] of n integers, find the 3 elements such that a[i] < a[j] < a[k] and i < j < k in O(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
Explanation: As 1 < 2 < 3, and they appear in the same sequence in the array
Input: arr[] = [4, 3, 2, 1]
Output: No such triplet exists.
Table of Content
[Naive Approach] - O(n) Time and O(n) Space
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.
- 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 the left side. The array contains -1 if there is no such element.
- 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 the right side of arr[i]. The array contains -1 if there is no such element.
- Finally traverse both smaller[] and greater[] and find the index [i] for which both smaller[i] and greater[i] are not equal to -1.
#include <iostream>
using namespace std;
// A function to find a sorted sub-sequence of size 3
vector<int> find3Numbers(vector<int> &arr)
{
int n = arr.size();
// Fill smaller[] such that smaller[i] stores the
// index of a smaller element on the left side
vector<int> smaller(n, -1);
int min = 0;
for (int i = 1; i < n; i++)
{
if (arr[i] <= arr[min])
min = i;
else
smaller[i] = min;
}
// Fill greater[] such that greater[i] stores the
// index of a greater element on the right side
vector<int> greater(n, -1);
int max = n - 1;
for (int i = n - 2; i >= 0; i--)
{
if (arr[i] >= arr[max])
max = i;
else
greater[i] = max;
}
// Find the triplet
for (int i = 0; i < n; i++)
{
if (smaller[i] != -1 && greater[i] != -1)
return {arr[smaller[i]], arr[i], arr[greater[i]]};
}
// If no such triplet is found, return an empty vector
return {};
}
int main()
{
vector<int> arr = {12, 11, 10, 5, 6, 2, 30};
vector<int> res = find3Numbers(arr);
for (int x : res)
cout << x << " ";
return 0;
}
import java.util.*;
class GfG {
// A function to find a sorted sub-sequence of size 3
static List<Integer> find3Numbers(int[] arr)
{
int n = arr.length;
// Fill smaller[] such that smaller[i] stores the
// index of a smaller element on the left side
int[] smaller = new int[n];
Arrays.fill(smaller, -1);
int min = 0;
for (int i = 1; i < n; i++)
{
if (arr[i] <= arr[min])
min = i;
else
smaller[i] = min;
}
// Fill greater[] such that greater[i] stores the
// index of a greater element on the right side
int[] greater = new int[n];
Arrays.fill(greater, -1);
int max = n - 1;
for (int i = n - 2; i >= 0; i--)
{
if (arr[i] >= arr[max])
max = i;
else
greater[i] = max;
}
// Find the triplet
for (int i = 0; i < n; i++)
{
if (smaller[i] != -1 && greater[i] != -1)
return Arrays.asList(arr[smaller[i]], arr[i], arr[greater[i]]);
}
// If no such triplet is found, return an empty vector
return new ArrayList<>();
}
public static void main(String[] args)
{
int[] arr = {12, 11, 10, 5, 6, 2, 30};
List<Integer> res = find3Numbers(arr);
for (int x : res)
System.out.print(x + " ");
}
}
# A function to find a sorted sub-sequence of size 3
def find3Numbers(arr):
n = len(arr)
# Fill smaller[] such that smaller[i] stores the
# index of a smaller element on the left side
smaller = [-1] * n
min = 0
for i in range(1, n):
if arr[i] <= arr[min]:
min = i
else:
smaller[i] = min
# Fill greater[] such that greater[i] stores the
# index of a greater element on the right side
greater = [-1] * n
max = n - 1
for i in range(n - 2, -1, -1):
if arr[i] >= arr[max]:
max = i
else:
greater[i] = max
# Find the triplet
for i in range(n):
if smaller[i] != -1 and greater[i] != -1:
return [arr[smaller[i]], arr[i], arr[greater[i]]]
# If no such triplet is found, return an empty vector
return []
# Driver code
arr = [12, 11, 10, 5, 6, 2, 30]
res = find3Numbers(arr)
for x in res:
print x,
using System;
using System.Collections.Generic;
class GfG {
// A function to find a sorted sub-sequence of size 3
static List<int> find3Numbers(int[] arr)
{
int n = arr.Length;
// Fill smaller[] such that smaller[i] stores the
// index of a smaller element on the left side
int[] smaller = new int[n];
for (int i = 0; i < n; i++) smaller[i] = -1;
int min = 0;
for (int i = 1; i < n; i++)
{
if (arr[i] <= arr[min])
min = i;
else
smaller[i] = min;
}
// Fill greater[] such that greater[i] stores the
// index of a greater element on the right side
int[] greater = new int[n];
for (int i = 0; i < n; i++) greater[i] = -1;
int max = n - 1;
for (int i = n - 2; i >= 0; i--)
{
if (arr[i] >= arr[max])
max = i;
else
greater[i] = max;
}
// Find the triplet
for (int i = 0; i < n; i++)
{
if (smaller[i] != -1 && greater[i] != -1)
return new List<int> { arr[smaller[i]], arr[i], arr[greater[i]] };
}
// If no such triplet is found, return an empty vector
return new List<int>();
}
static void Main()
{
int[] arr = {12, 11, 10, 5, 6, 2, 30};
List<int> res = find3Numbers(arr);
foreach (int x in res)
Console.Write(x + " ");
}
}
/* A function to find a sorted sub-sequence of size 3 */
function find3Numbers(arr) {
const n = arr.length;
// Fill smaller[] such that smaller[i] stores the
// index of a smaller element on the left side
const smaller = new Array(n).fill(-1);
let min = 0;
for (let i = 1; i < n; i++) {
if (arr[i] <= arr[min])
min = i;
else
smaller[i] = min;
}
// Fill greater[] such that greater[i] stores the
// index of a greater element on the right side
const greater = new Array(n).fill(-1);
let max = n - 1;
for (let i = n - 2; i >= 0; i--) {
if (arr[i] >= arr[max])
max = i;
else
greater[i] = max;
}
// Find the triplet
for (let i = 0; i < n; i++) {
if (smaller[i]!== -1 && greater[i]!== -1)
return [arr[smaller[i]], arr[i], arr[greater[i]]];
}
// If no such triplet is found, return an empty array
return [];
}
// Driver code
const arr = [12, 11, 10, 5, 6, 2, 30];
const res = find3Numbers(arr);
for (const x of res) {
console.log(x + " ");
}
Output
5 6 30
[Expected Approach] - O(n) Time and O(1) Space
First find two elements arr[i] & arr[j] such that arr[i] < arr[j]. Then find a third element arr[k] greater than arr[j]. We can think of the problem in three simple terms.
- First we only need to find two elements arr[i] < arr[j] and i < j. This can be done in linear time with just 1 loop over the range of the array. For instance, while keeping track of the min element, it is easy to find any subsequent element that is greater than it. Thus we have our arr[i] & arr[j]. Consider {3, 4, -1, 0, 2}. Initially min is 3, arr[i] is 3 and arr[j] is 4. While iterating over the array we can easily keep track of min and eventually update it to -1, so arr[i] & arr[j] become -1 and 0.
- As soon as we have arr[i] & arr[j] values, we can immediately start monitoring the subsequent elements in the same loop for an arr[k] > arr[j]. Thus we can find all three values arr[i] < arr[j] < arr[k] in a single pass over the array.
#include <iostream>
using namespace std;
vector<int> find3Numbers(vector<int> &arr) {
int n = arr.size();
if (n < 3)
return {};
int first = INT_MAX;
int second = INT_MAX;
int prevFirst = INT_MAX;
// Iterating through the array
for (int i = 0; i < n; i++) {
int x = arr[i];
// Updating first and second smallest numbers
if (x <= first) {
first = x;
} else if (x <= second) {
second = x;
prevFirst = first;
}
// If a third number greater than first and second is found
else {
return {prevFirst, second, x};
}
}
return {};
}
int main() {
vector<int> arr = {12, 11, 10, 5, 6, 2, 30};
vector<int> res = find3Numbers(arr);
for (int x : res)
cout << x << " ";
return 0;
}
import java.util.*;
class GfG {
static List<Integer> find3Numbers(int[] arr) {
int n = arr.length;
if (n < 3)
return new ArrayList<>();
int first = Integer.MAX_VALUE;
int second = Integer.MAX_VALUE;
int prevFirst = Integer.MAX_VALUE;
// Iterating through the array
for (int i = 0; i < n; i++) {
int x = arr[i];
// Updating first and second smallest numbers
if (x <= first) {
first = x;
} else if (x <= second) {
second = x;
prevFirst = first;
}
// If a third number greater than first and second is found
else {
return Arrays.asList(prevFirst, second, x);
}
}
return new ArrayList<>();
}
public static void main(String[] args) {
int[] arr = {12, 11, 10, 5, 6, 2, 30};
List<Integer> res = find3Numbers(arr);
for (int x : res)
System.out.print(x + " ");
}
}
def find3Numbers(arr):
n = len(arr)
if n < 3:
return []
first = float('inf')
second = float('inf')
prevFirst = float('inf')
# Iterating through the array
for i in range(n):
x = arr[i]
# Updating first and second smallest numbers
if x <= first:
first = x
elif x <= second:
second = x
prevFirst = first
# If a third number greater than first and second is found
else:
return [prevFirst, second, x]
return []
# driver code
arr = [12, 11, 10, 5, 6, 2, 30]
res = find3Numbers(arr)
for x in res:
print(x, end=" ")
using System;
using System.Collections.Generic;
class GfG {
static List<int> find3Numbers(int[] arr) {
int n = arr.Length;
if (n < 3)
return new List<int>();
int first = int.MaxValue;
int second = int.MaxValue;
int prevFirst = int.MaxValue;
// Iterating through the array
for (int i = 0; i < n; i++) {
int x = arr[i];
// Updating first and second smallest numbers
if (x <= first) {
first = x;
} else if (x <= second) {
second = x;
prevFirst = first;
}
// If a third number greater than first and second is found
else {
return new List<int> { prevFirst, second, x };
}
}
return new List<int>();
}
static void Main() {
int[] arr = { 12, 11, 10, 5, 6, 2, 30 };
List<int> res = find3Numbers(arr);
foreach (int x in res)
Console.Write(x + " ");
}
}
function find3Numbers(arr) {
let n = arr.length;
if (n < 3)
return [];
let first = Number.MAX_VALUE;
let second = Number.MAX_VALUE;
let prevFirst = Number.MAX_VALUE;
// Iterating through the array
for (let i = 0; i < n; i++) {
let x = arr[i];
// Updating first and second smallest numbers
if (x <= first) {
first = x;
} else if (x <= second) {
second = x;
prevFirst = first;
}
// If a third number greater than first and second is found
else {
return [prevFirst, second, x];
}
}
return [];
}
function main() {
let arr = [12, 11, 10, 5, 6, 2, 30];
let res = find3Numbers(arr);
console.log(res.join(" "));
}
main();
Output
5 6 30