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 find the farthest smaller element to the right for each arr[i], we want a way to quickly know if a smaller element exists further ahead and how far it is.
Instead of scanning all elements to the right of every index, we can 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