Given an array arr[] of size n. For each element arr[i] (0-based indexing), find the index of the farthest element to its right (i.e., having a greater index) such that arr[j] < arr[i] and j > i. If no such element exists, return -1 for that position.
Examples:
Input: arr[] = [2, 5, 1, 3, 2]
Output: [2, 4, -1, 4, -1]
Explanation: arr[0] = 2: Farthest smaller element to the right is arr[2] = 1 → index 2.
arr[1] = 5: Farthest smaller element to the right is arr[4] = 2 → index 4.
arr[2] = 1: No smaller element to the right → -1.
arr[3] = 3: Farthest smaller element to the right is arr[4] = 2 → index 4.
arr[4] = 2: No elements to the right → -1.Input: arr[] = [2, 3, 5, 4, 1]
Output: [4, 4, 4, 4, -1]
Explanation: arr[4] is the farthest smallest element to the right for arr[0], arr[1], arr[2] and arr[3].
Table of Content
[Naive Approach] Checking Each Element in Right – O(n^2) Time and O(1) Space
A brute force approach to this problem can be, keep a variable idx = -1 from beginning and for each element start traversing the same array from the backward upto (i+1)th index. And, if any element at index j is smaller than the current element, i.e. (a[i] > a[j]) break from the loop, and return the jth index.
#include <iostream>
#include <vector>
using namespace std;
vector<int> farMin(vector<int>& arr) {
int n = arr.size();
vector<int> ans(n, -1);
for (int i = 0; i < n; ++i) {
// check from the end to find the farthest smaller
for (int j = n - 1; j > i; --j) {
// update with the farthest valid index
// break since we need the farthest (rightmost)
if (arr[j] < arr[i]) {
ans[i] = j;
break;
}
}
}
return ans;
}
int main() {
vector<int> arr = {2, 5, 1, 3, 2};
vector<int> res = farMin(arr);
for (int x : res)
cout << x << " ";
cout << endl;
return 0;
}
import java.util.ArrayList;
import java.util.Arrays;
public class GfG {
static ArrayList<Integer> farMin(int[] arr) {
int n = arr.length;
ArrayList<Integer> ans = new ArrayList<>(n);
for (int i = 0; i < n; ++i) {
ans.add(-1);
}
for (int i = 0; i < n; ++i) {
// check from the end to find the farthest smaller
for (int j = n - 1; j > i; --j) {
// update with the farthest valid index
// break since we need the farthest (rightmost)
if (arr[j] < arr[i]) {
ans.set(i, j);
break;
}
}
}
return ans;
}
public static void main(String[] args) {
int[] arr = {2, 5, 1, 3, 2};
ArrayList<Integer> res = farMin(arr);
for (int x : res)
System.out.print(x + " ");
System.out.println();
}
}
def farMin(arr):
n = len(arr)
ans = [-1] * n
for i in range(n):
# check from the end to find the farthest smaller
for j in range(n - 1, i, -1):
# update with the farthest valid index
# break since we need the farthest (rightmost)
if arr[j] < arr[i]:
ans[i] = j
break
return ans
if __name__ == '__main__':
arr = [2, 5, 1, 3, 2]
res = farMin(arr)
for x in res:
print(x, end=' ')
print()
using System;
using System.Collections.Generic;
public class GfG {
static List<int> farMin(int[] arr) {
int n = arr.Length;
List<int> ans = new List<int>(new int[n]);
for (int i = 0; i < n; i++) {
ans[i] = -1;
}
for (int i = 0; i < n; ++i) {
// check from the end to find the farthest smaller
for (int j = n - 1; j > i; --j) {
// update with the farthest valid index
// break since we need the farthest (rightmost)
if (arr[j] < arr[i]) {
ans[i] = j;
break;
}
}
}
return ans;
}
public static void Main()
{
int[] arr = { 2, 5, 1, 3, 2 };
List<int> res = farMin(arr);
foreach (int x in res)
Console.Write(x + " ");
Console.WriteLine();
}
}
function farMin(arr) {
let n = arr.length;
let ans = new Array(n).fill(-1);
for (let i = 0; i < n; ++i) {
// check from the end to find the farthest smaller
for (let j = n - 1; j > i; --j) {
// update with the farthest valid index
// break since we need the farthest (rightmost)
if (arr[j] < arr[i]) {
ans[i] = j;
break;
}
}
}
return ans;
}
// Driver Code
let arr = [2, 5, 1, 3, 2];
let res = farMin(arr);
console.log(res.join(' '));
Output
2 4 -1 4 -1
[Expected Approach] Binary Search – O(n*log(n)) Time and O(n) Space
The idea is to precompute the minimum values in all suffixes of the array. This allows us to efficiently search for the farthest valid position using binary search.
Step By Step Implementations:
- Suffix Minimum Array
-> For each position in the array, store the minimum value among all elements from that index to the end.
-> This allows us to know quickly if there's any smaller element on the right. - Binary Search for Each Element
-> For every element arr[i], use binary search on the suffix minimum array to find the farthest index j > i such that the value at j is smaller than arr[i].
-> We try to go as far as possible to the right while the condition holds. - Store and Return Results
-> If such an index is found, store it.
-> If not, store -1 for that position.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
vector<int> farMin(vector<int>& arr) {
int n = arr.size();
vector<int> ans(n, -1);
// build suffix min array
vector<int> suff(n);
suff[n - 1] = arr[n - 1];
for (int i = n - 2; i >= 0; --i)
suff[i] = min(arr[i], suff[i + 1]);
// binary search on suffix for farthest smaller element
for (int i = 0; i < n; ++i) {
int lo = i + 1, hi = n - 1, res = -1;
while (lo <= hi) {
int mid = (lo + hi) / 2;
if (suff[mid] < arr[i]) {
res = mid;
lo = mid + 1;
} else {
hi = mid - 1;
}
}
ans[i] = res;
}
return ans;
}
int main() {
vector<int> arr = {2, 5, 1, 3, 2};
vector<int> res = farMin(arr);
for (int x : res)
cout << x << " ";
cout << endl;
return 0;
}
import java.util.ArrayList;
import java.util.Collections;
class GfG {
static ArrayList<Integer> farMin(int[] arr) {
int n = arr.length;
ArrayList<Integer> ans = new ArrayList<>(Collections.nCopies(n, -1));
ArrayList<Integer> arrList = new ArrayList<>(n);
for (int i : arr) arrList.add(i);
// build suffix min array
ArrayList<Integer> suff = new ArrayList<>(arrList);
suff.set(n - 1, arrList.get(n - 1));
for (int i = n - 2; i >= 0; --i)
suff.set(i, Math.min(arrList.get(i), suff.get(i + 1)));
// binary search on suffix for farthest smaller element
for (int i = 0; i < n; ++i) {
int lo = i + 1, hi = n - 1, res = -1;
while (lo <= hi) {
int mid = (lo + hi) / 2;
if (suff.get(mid) < arrList.get(i)) {
res = mid;
lo = mid + 1;
} else {
hi = mid - 1;
}
}
ans.set(i, res);
}
return ans;
}
public static void main(String[] args) {
int[] arr = {2, 5, 1, 3, 2};
ArrayList<Integer> arrList = new ArrayList<>(arr.length);
for (int i : arr) arrList.add(i);
ArrayList<Integer> res = farMin(arr);
for (int x : res)
System.out.print(x + " ");
System.out.println();
}
}
def farMin(arr):
n = len(arr)
ans = [-1] * n
# build suffix min array
suff = arr.copy()
suff[n - 1] = arr[n - 1]
for i in range(n - 2, -1, -1):
suff[i] = min(arr[i], suff[i + 1])
# binary search on suffix for farthest smaller element
for i in range(n):
lo, hi, res = i + 1, n - 1, -1
while lo <= hi:
mid = (lo + hi) // 2
if suff[mid] < arr[i]:
res = mid
lo = mid + 1
else:
hi = mid - 1
ans[i] = res
return ans
if __name__ == "__main__":
arr = [2, 5, 1, 3, 2]
res = farMin(arr)
print(" ".join(map(str, res)))
using System;
using System.Collections.Generic;
class GfG {
static List<int> farMin(int[] arr) {
int n = arr.Length;
List<int> ans = new List<int>(new int[n]);
ans.ForEach(x => x = -1);
// build suffix min array
List<int> suff = new List<int>(arr);
suff[n - 1] = arr[n - 1];
for (int i = n - 2; i >= 0; --i)
suff[i] = Math.Min(arr[i], suff[i + 1]);
// binary search on suffix for farthest smaller element
for (int i = 0; i < n; ++i)
{
int lo = i + 1, hi = n - 1, res = -1;
while (lo <= hi)
{
int mid = (lo + hi) / 2;
if (suff[mid] < arr[i])
{
res = mid;
lo = mid + 1;
}
else
{
hi = mid - 1;
}
}
ans[i] = res;
}
return ans;
}
public static void Main()
{
int[] arr = { 2, 5, 1, 3, 2 };
List<int> res = farMin(arr);
foreach (int x in res)
Console.Write(x + " ");
Console.WriteLine();
}
}
function farMin(arr) {
const n = arr.length;
const ans = Array(n).fill(-1);
// build suffix min array
const suff = [...arr];
suff[n - 1] = arr[n - 1];
for (let i = n - 2; i >= 0; --i)
suff[i] = Math.min(arr[i], suff[i + 1]);
// binary search on suffix for farthest smaller element
for (let i = 0; i < n; ++i) {
let lo = i + 1, hi = n - 1, res = -1;
while (lo <= hi) {
const mid = Math.floor((lo + hi) / 2);
if (suff[mid] < arr[i]) {
res = mid;
lo = mid + 1;
} else {
hi = mid - 1;
}
}
ans[i] = res;
}
return ans;
}
// Driver Code
const arr = [2, 5, 1, 3, 2];
const res = farMin(arr);
console.log(res.join(' '));
Output
2 4 -1 4 -1