Finding nearest shortest tower in Array
Last Updated :
29 Oct, 2023
Given an array arr[] where each element (arr[i]) represents the height of the tower. Find the nearest possible tower that is shorter than it for each tower. You can look left or right on both sides.
- If two smaller towers are at the same distance, pick the smallest tower.
- If two towers have the same height, we choose the one with a smaller index.
Examples:
Input: arr[] = {1, 3, 2}
Output: {-1, 0, 0}
Explanation:
- For 0th Index: no tower is smallest, so -1.
- For 1st Index: For 3, here 1 & 2 both are small & at the same distance, so we will pick 1 because it has the smallest value, so 0(Index)
- For 2nd Index : here 1 is smaller, so 0(Index) So the final output will be which consists Indexes are {-1, 0, 0}.
Input: arr[] = {4, 8, 3, 5, 3}
Output: {2, 2, -1, 2, -1}
Explanation:
- For 0th Index: here 3 is the smaller, so 2(Index)
- For 1st Index: For 8, here 4 & 3 both are small & at the same distance, so we will pick 3, so 2(Index)
- For the 2nd Index: no tower is smallest, so -1.
- For 3rd Index : For 5, here 3 & 3 both are small & at a same distance, so we will pick 3(2nd Index) because it smaller Index, so 2(Index)
- For 4th Index: no tower is smallest, so -1. So the final output will be which consist of Indexes {2, 2, -1, 2, -1}.
Approach: This can be solved with the following idea:
The idea is to use two stacks to find the nearest smaller tower on the left and on the right for each tower in the array. It first finds the nearest smaller tower on the left for each tower using a stack, then finds the nearest smaller tower on the right for each tower using another stack. Finally, we compare the nearest smaller towers on the left and on the right for each tower and choose the tower with the smaller height if there are two towers at the same distance.
Below are the steps involved in the implementation of the code:
- Initializes an array res of length n with -1, where n is the length of the input array arr. This array will store the index of the nearest smaller tower for each tower in the input array.
- Use a stack pre to find the index of the nearest smaller tower to the left of the current tower. For each tower, I in the input array, pop all the indices from pre until it finds an index whose corresponding tower has a smaller height than the current tower arr[i]. The index of this smaller tower is then stored in res[i]. Finally, the current index i is pushed onto pre.
- Similarly, create another stack for storing smaller elements on the right side of the current tower.
- For each tower, i in the input array (in reverse order), pop all the indices from suf until it finds an index whose corresponding tower has a smaller height than the current tower arr[i].
- If the res[i] already contains an index (i.e., a smaller tower has already been found to the left of the current tower), then the algorithm compares the distance of the index found by suf to the current index i with the distance of the index stored in res[i] to i.
- If the distances are the same, then the algorithm chooses the tower with the smaller height; if the distances are different, then the algorithm chooses the tower that is closer to the current tower.
- If res[i] is not yet initialized (i.e., no smaller tower has been found to the left of the current tower), then the index found by suf is stored in res[i].
- Finally, the current index i is pushed onto suf.:
Below is the implementation of the above code:
C++
#include <bits/stdc++.h>
using namespace std;
vector< int > nearestSmallerTower(vector< int >& arr)
{
int n = arr.size();
stack< int > pre, suf;
vector< int > res(n, -1);
for ( int i = 0; i < n; i++) {
while (!pre.empty() && arr[pre.top()] >= arr[i]) {
pre.pop();
}
if (!pre.empty()) {
res[i] = pre.top();
}
pre.push(i);
}
for ( int i = n - 1; i >= 0; i--) {
while (!suf.empty() && arr[suf.top()] >= arr[i]) {
suf.pop();
}
if (!suf.empty()) {
if (res[i] != -1) {
if ( abs (res[i] - i) == abs (suf.top() - i)) {
if (arr[res[i]] > arr[suf.top()])
res[i] = suf.top();
}
else if ( abs (res[i] - i)
> abs (suf.top() - i))
res[i] = suf.top();
}
else
res[i] = suf.top();
}
suf.push(i);
}
return res;
}
int main()
{
vector< int > arr = { 1, 3, 2 };
vector< int > ans = nearestSmallerTower(arr);
for ( auto it : ans)
cout << it << " " ;
return 0;
}
|
Java
import java.util.*;
public class NearestSmallerTower {
public static List<Integer> nearestSmallerTower(List<Integer> arr) {
int n = arr.size();
Stack<Integer> pre = new Stack<>();
Stack<Integer> suf = new Stack<>();
List<Integer> res = new ArrayList<>(Collections.nCopies(n, - 1 ));
for ( int i = 0 ; i < n; i++) {
while (!pre.isEmpty() && arr.get(pre.peek()) >= arr.get(i)) {
pre.pop();
}
if (!pre.isEmpty()) {
res.set(i, pre.peek());
}
pre.push(i);
}
for ( int i = n - 1 ; i >= 0 ; i--) {
while (!suf.isEmpty() && arr.get(suf.peek()) >= arr.get(i)) {
suf.pop();
}
if (!suf.isEmpty()) {
if (res.get(i) != - 1 ) {
if (Math.abs(res.get(i) - i) == Math.abs(suf.peek() - i)) {
if (arr.get(res.get(i)) > arr.get(suf.peek())) {
res.set(i, suf.peek());
}
} else if (Math.abs(res.get(i) - i) > Math.abs(suf.peek() - i)) {
res.set(i, suf.peek());
}
} else {
res.set(i, suf.peek());
}
}
suf.push(i);
}
return res;
}
public static void main(String[] args) {
List<Integer> arr = Arrays.asList( 1 , 3 , 2 );
List<Integer> ans = nearestSmallerTower(arr);
for ( int it : ans) {
System.out.print(it + " " );
}
}
}
|
Python3
def nearest_smaller_tower(arr):
n = len (arr)
pre = []
suf = []
res = [ - 1 ] * n
for i in range (n):
while pre and arr[pre[ - 1 ]] > = arr[i]:
pre.pop()
if pre:
res[i] = pre[ - 1 ]
pre.append(i)
for i in range (n - 1 , - 1 , - 1 ):
while suf and arr[suf[ - 1 ]] > = arr[i]:
suf.pop()
if suf:
if res[i] ! = - 1 :
if abs (res[i] - i) = = abs (suf[ - 1 ] - i):
if arr[res[i]] > arr[suf[ - 1 ]]:
res[i] = suf[ - 1 ]
elif abs (res[i] - i) > abs (suf[ - 1 ] - i):
res[i] = suf[ - 1 ]
else :
res[i] = suf[ - 1 ]
suf.append(i)
return res
arr = [ 1 , 3 , 2 ]
ans = nearest_smaller_tower(arr)
for it in ans:
print (it, end = ' ' )
|
C#
using System;
public class TowerIndices
{
public static int [] FindSmallestTowerIndices( int [] arr)
{
int n = arr.Length;
int [] result = new int [n];
for ( int i = 0; i < n; i++)
{
int closestSmaller = -1;
int minDistance = int .MaxValue;
for ( int j = i - 1; j >= 0; j--)
{
if (arr[j] < arr[i])
{
int distance = i - j;
if (distance < minDistance)
{
minDistance = distance;
closestSmaller = j;
}
}
}
result[i] = closestSmaller;
}
return result;
}
public static void Main( string [] args)
{
int [] arr = { 1, 3, 2 };
int [] result = FindSmallestTowerIndices(arr);
Console.WriteLine( "{" + string .Join( ", " , result) + "}" );
}
}
|
Javascript
function nearestSmallerTower(arr) {
let n = arr.length;
let pre = [];
let suf = [];
let res = new Array(n).fill(-1);
for (let i = 0; i < n; i++) {
while (pre.length > 0 && arr[pre[pre.length - 1]] >= arr[i]) {
pre.pop();
}
if (pre.length > 0) {
res[i] = pre[pre.length - 1];
}
pre.push(i);
}
for (let i = n - 1; i >= 0; i--) {
while (suf.length > 0 && arr[suf[suf.length - 1]] >= arr[i]) {
suf.pop();
}
if (suf.length > 0) {
if (res[i] != -1) {
if (Math.abs(res[i] - i) == Math.abs(suf[suf.length - 1] - i)) {
if (arr[res[i]] > arr[suf[suf.length - 1]]) {
res[i] = suf[suf.length - 1];
}
} else if (Math.abs(res[i] - i) > Math.abs(suf[suf.length - 1] - i)) {
res[i] = suf[suf.length - 1];
}
} else {
res[i] = suf[suf.length - 1];
}
}
suf.push(i);
}
return res;
}
let arr = [1, 3, 2];
let ans = nearestSmallerTower(arr);
for (let it of ans) {
console.log(it + " " );
}
|
Time Complexity: O(N+N)
Auxiliary Space: O(N+N+N)
Like Article
Suggest improvement
Share your thoughts in the comments
Please Login to comment...