Given an array arr[], find an element before which all elements are equal or smaller than it, and after which all the elements are equal or greater.
Note: Print -1, if no such element exists.
Examples:
Input: arr[] = [5, 1, 4, 3, 6, 8, 10, 7, 9]
Output: 6
Explanation: 6 is present at index 4. All elements on the left of arr[4] are smaller than it and all elements on right are greater.Input: arr[] = [5, 1, 4, 4]
Output: -1
Explanation: No such element exists.
Table of Content
[Naive Approach] Using Nested Loops - O(n2) Time and O(1) Space
The idea is to consider every non-boundary element of the given array arr[] one by one. For each element, find the largest element in left of it, and the smallest element in the right of it using the nested loops. If the largest element in its left is smaller or equal and the smallest element in its right is greater or equal, print the current element, else move to next. At last if no such element is found, print -1.
#include <iostream>
#include <vector>
#include <algorithm>
#include <climits>
using namespace std;
int findElement(vector<int> &arr) {
// Iteratte through each elements
for(int i = 1; i < arr.size() - 1; i++) {
// to store maximum in left
int left = INT_MIN;
for(int j = 0; j < i; j++) {
left = max(left, arr[j]);
}
// to store minimum in right
int right = INT_MAX;
for(int j = i + 1; j < arr.size(); j++) {
right = min(right, arr[j]);
}
// check if current element is greater
// than left and smaller than right (or equal)
if(arr[i] >= left && arr[i] <= right) {
return arr[i];
}
}
return -1;
}
int main() {
vector<int> arr = {5, 1, 4, 3, 6, 8, 10, 7, 9};
cout << findElement(arr);
return 0;
}
class GfG {
static int findElement(int[] arr) {
// Iterate through each element
for(int i = 1; i < arr.length - 1; i++) {
// to store maximum in left
int left = Integer.MIN_VALUE;
for(int j = 0; j < i; j++) {
left = Math.max(left, arr[j]);
}
// to store minimum in right
int right = Integer.MAX_VALUE;
for(int j = i + 1; j < arr.length; j++) {
right = Math.min(right, arr[j]);
}
// check if current element is greater
// than left and smaller than right (or equal)
if(arr[i] >= left && arr[i] <= right) {
return arr[i];
}
}
return -1;
}
public static void main(String[] args) {
int[] arr = {5, 1, 4, 3, 6, 8, 10, 7, 9};
System.out.println(findElement(arr));
}
}
def findElement(arr):
# Iterate through each element
for i in range(1, len(arr) - 1):
# to store maximum in left
left = float('-inf')
for j in range(i):
left = max(left, arr[j])
# to store minimum in right
right = float('inf')
for j in range(i + 1, len(arr)):
right = min(right, arr[j])
# check if current element is greater
# than left and smaller than right (or equal)
if arr[i] >= left and arr[i] <= right:
return arr[i]
return -1
if __name__ == "__main__":
arr = [5, 1, 4, 3, 6, 8, 10, 7, 9]
print(findElement(arr))
using System;
class GfG {
static int findElement(int[] arr) {
// Iterate through each element
for(int i = 1; i < arr.Length - 1; i++) {
// to store maximum in left
int left = int.MinValue;
for(int j = 0; j < i; j++) {
left = Math.Max(left, arr[j]);
}
// to store minimum in right
int right = int.MaxValue;
for(int j = i + 1; j < arr.Length; j++) {
right = Math.Min(right, arr[j]);
}
// check if current element is greater
// than left and smaller than right (or equal)
if(arr[i] >= left && arr[i] <= right) {
return arr[i];
}
}
return -1;
}
public static void Main() {
int[] arr = {5, 1, 4, 3, 6, 8, 10, 7, 9};
Console.WriteLine(findElement(arr));
}
}
function findElement(arr) {
// Iterate through each element
for(let i = 1; i < arr.length - 1; i++) {
// to store maximum in left
let left = -Infinity;
for(let j = 0; j < i; j++) {
left = Math.max(left, arr[j]);
}
// to store minimum in right
let right = Infinity;
for(let j = i + 1; j < arr.length; j++) {
right = Math.min(right, arr[j]);
}
// check if current element is greater
// than left and smaller than right (or equal)
if(arr[i] >= left && arr[i] <= right) {
return arr[i];
}
}
return -1;
}
// Driver Code
let arr = [5, 1, 4, 3, 6, 8, 10, 7, 9];
console.log(findElement(arr));
Output
6
[Expected Approach 1] Using Prefix and Suffix Arrays - O(n) Time and O(n) Space
The idea is to precompute the largest values from index 0 to n - 1 and smallest values from n - 1 to 0. To do so,
- Create two arrays leftMax[] and rightMin[].
- Traverse input array from left to right and fill leftMax[] such that leftMax[i] contains the maximum element from 0 to i-1 in the input array.
- Traverse input array from right to left and fill rightMin[] such that rightMin[i] contains the minimum element from n-1 to i+1 in the input array.
- Traverse input array. For every element arr[i], check if arr[i] is greater than or equals to leftMax[i] and smaller than or equals to rightMin[i]. If true, return arr[i]
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int findElement(vector<int> &arr) {
int n = arr.size();
// leftMax[i] stores maximum of arr[0..i]
vector<int> leftMax(n);
leftMax[0] = arr[0];
// Fill leftMax[1..n-1]
for (int i = 1; i < n; i++)
leftMax[i] = max(leftMax[i-1], arr[i]);
// rightMin[i] stores minimum of arr[i..n - 1]
vector<int> rightMin(n);
rightMin[n - 1] = arr[n - 1];
// Fill rightMin[1..n-1]
for (int i = n - 2; i >= 0; i--)
rightMin[i] = min(rightMin[i+1], arr[i]);
// Check if we found a required element
for(int i = 1; i < n - 1; i++) {
if(arr[i] >= leftMax[i] && arr[i] <= rightMin[i]) {
return arr[i];
}
}
return -1;
}
int main() {
vector<int> arr = {5, 1, 4, 3, 6, 8, 10, 7, 9};
cout << findElement(arr);
return 0;
}
class GfG {
static int findElement(int[] arr) {
int n = arr.length;
// leftMax[i] stores maximum of arr[0..i]
int[] leftMax = new int[n];
leftMax[0] = arr[0];
// Fill leftMax[1..n-1]
for (int i = 1; i < n; i++)
leftMax[i] = Math.max(leftMax[i - 1], arr[i]);
// rightMin[i] stores minimum of arr[i..n - 1]
int[] rightMin = new int[n];
rightMin[n - 1] = arr[n - 1];
// Fill rightMin[1..n-1]
for (int i = n - 2; i >= 0; i--)
rightMin[i] = Math.min(rightMin[i + 1], arr[i]);
// Check if we found a required element
for (int i = 1; i < n - 1; i++) {
if (arr[i] >= leftMax[i] && arr[i] <= rightMin[i]) {
return arr[i];
}
}
return -1;
}
public static void main(String[] args) {
int[] arr = {5, 1, 4, 3, 6, 8, 10, 7, 9};
System.out.println(findElement(arr));
}
}
def findElement(arr):
n = len(arr)
# leftMax[i] stores maximum of arr[0..i]
leftMax = [0] * n
leftMax[0] = arr[0]
# Fill leftMax[1..n-1]
for i in range(1, n):
leftMax[i] = max(leftMax[i - 1], arr[i])
# rightMin[i] stores minimum of arr[i..n - 1]
rightMin = [0] * n
rightMin[n - 1] = arr[n - 1]
# Fill rightMin[1..n-1]
for i in range(n - 2, -1, -1):
rightMin[i] = min(rightMin[i + 1], arr[i])
# Check if we found a required element
for i in range(1, n - 1):
if arr[i] >= leftMax[i] and arr[i] <= rightMin[i]:
return arr[i]
return -1
if __name__ == '__main__':
arr = [5, 1, 4, 3, 6, 8, 10, 7, 9]
print(findElement(arr))
using System;
class GfG {
static int findElement(int[] arr) {
int n = arr.Length;
// leftMax[i] stores maximum of arr[0..i]
int[] leftMax = new int[n];
leftMax[0] = arr[0];
// Fill leftMax[1..n-1]
for (int i = 1; i < n; i++)
leftMax[i] = Math.Max(leftMax[i - 1], arr[i]);
// rightMin[i] stores minimum of arr[i..n - 1]
int[] rightMin = new int[n];
rightMin[n - 1] = arr[n - 1];
// Fill rightMin[1..n-1]
for (int i = n - 2; i >= 0; i--)
rightMin[i] = Math.Min(rightMin[i + 1], arr[i]);
// Check if we found a required element
for (int i = 1; i < n - 1; i++) {
if (arr[i] >= leftMax[i] && arr[i] <= rightMin[i]) {
return arr[i];
}
}
return -1;
}
static void Main() {
int[] arr = {5, 1, 4, 3, 6, 8, 10, 7, 9};
Console.WriteLine(findElement(arr));
}
}
function findElement(arr) {
let n = arr.length;
// leftMax[i] stores maximum of arr[0..i]
let leftMax = new Array(n);
leftMax[0] = arr[0];
// Fill leftMax[1..n-1]
for (let i = 1; i < n; i++)
leftMax[i] = Math.max(leftMax[i - 1], arr[i]);
// rightMin[i] stores minimum of arr[i..n - 1]
let rightMin = new Array(n);
rightMin[n - 1] = arr[n - 1];
// Fill rightMin[1..n-1]
for (let i = n - 2; i >= 0; i--)
rightMin[i] = Math.min(rightMin[i + 1], arr[i]);
// Check if we found a required element
for (let i = 1; i < n - 1; i++) {
if (arr[i] >= leftMax[i] && arr[i] <= rightMin[i]) {
return arr[i];
}
}
return -1;
}
// Driver Code
let arr = [5, 1, 4, 3, 6, 8, 10, 7, 9];
console.log(findElement(arr));
Output
6
[Expected Approach 2] Using Prefix Array - O(n) Time and O(n) Space
The idea is to create a single array leftMax[] to store the largest elements at left of each index. And for right minimum values, we can use an integer rightMin that will store the current minimum value. At each iteration update the value rightMin and compare it with current value arr[i].
Below image is a dry run of the above approach:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int findElement(vector<int> &arr) {
int n = arr.size();
// leftMax[i] stores maximum of arr[0..i]
vector<int> leftMax(n);
leftMax[0] = arr[0];
// Fill leftMax[1..n-1]
for (int i = 1; i < n; i++)
leftMax[i] = max(leftMax[i-1], arr[i]);
// rightMin to store the minimum value
int rightMin = arr[n-1];
// Check if we found a required element
for(int i = n - 2; i > 0; i--) {
if(arr[i] >= leftMax[i] && arr[i] <= rightMin) {
return arr[i];
}
// update rightMin
rightMin = min(rightMin, arr[i]);
}
return -1;
}
int main() {
vector<int> arr = {5, 1, 4, 3, 6, 8, 10, 7, 9};
cout << findElement(arr);
return 0;
}
class GfG {
static int findElement(int[] arr) {
int n = arr.length;
// leftMax[i] stores maximum of arr[0..i]
int[] leftMax = new int[n];
leftMax[0] = arr[0];
// Fill leftMax[1..n-1]
for (int i = 1; i < n; i++)
leftMax[i] = Math.max(leftMax[i - 1], arr[i]);
// rightMin to store the minimum value
int rightMin = arr[n - 1];
// Check if we found a required element
for (int i = n - 2; i > 0; i--) {
if (arr[i] >= leftMax[i] && arr[i] <= rightMin) {
return arr[i];
}
// update rightMin
rightMin = Math.min(rightMin, arr[i]);
}
return -1;
}
public static void main(String[] args) {
int[] arr = {5, 1, 4, 3, 6, 8, 10, 7, 9};
System.out.println(findElement(arr));
}
}
def findElement(arr):
n = len(arr)
# leftMax[i] stores maximum of arr[0..i]
leftMax = [0] * n
leftMax[0] = arr[0]
# Fill leftMax[1..n-1]
for i in range(1, n):
leftMax[i] = max(leftMax[i - 1], arr[i])
# rightMin to store the minimum value
rightMin = arr[n - 1]
# Check if we found a required element
for i in range(n - 2, 0, -1):
if arr[i] >= leftMax[i] and arr[i] <= rightMin:
return arr[i]
# update rightMin
rightMin = min(rightMin, arr[i])
return -1
if __name__ == '__main__':
arr = [5, 1, 4, 3, 6, 8, 10, 7, 9]
print(findElement(arr))
using System;
class GfG {
static int findElement(int[] arr) {
int n = arr.Length;
// leftMax[i] stores maximum of arr[0..i]
int[] leftMax = new int[n];
leftMax[0] = arr[0];
// Fill leftMax[1..n-1]
for (int i = 1; i < n; i++)
leftMax[i] = Math.Max(leftMax[i - 1], arr[i]);
// rightMin to store the minimum value
int rightMin = arr[n - 1];
// Check if we found a required element
for (int i = n - 2; i > 0; i--) {
if (arr[i] >= leftMax[i] && arr[i] <= rightMin) {
return arr[i];
}
// update rightMin
rightMin = Math.Min(rightMin, arr[i]);
}
return -1;
}
static void Main() {
int[] arr = {5, 1, 4, 3, 6, 8, 10, 7, 9};
Console.WriteLine(findElement(arr));
}
}
function findElement(arr) {
let n = arr.length;
// leftMax[i] stores maximum of arr[0..i]
let leftMax = new Array(n);
leftMax[0] = arr[0];
// Fill leftMax[1..n-1]
for (let i = 1; i < n; i++)
leftMax[i] = Math.max(leftMax[i - 1], arr[i]);
// rightMin to store the minimum value
let rightMin = arr[n - 1];
// Check if we found a required element
for (let i = n - 2; i > 0; i--) {
if (arr[i] >= leftMax[i] && arr[i] <= rightMin) {
return arr[i];
}
// update rightMin
rightMin = Math.min(rightMin, arr[i]);
}
return -1;
}
// Driver Code
let arr = [5, 1, 4, 3, 6, 8, 10, 7, 9];
console.log(findElement(arr));
Output
6