Open In App

Finding nearest shortest tower in Array

Last Updated : 29 Oct, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

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++




// C++ code of the above approach
#include <bits/stdc++.h>
using namespace std;
 
// Function to find nearest smallest tower
vector<int> nearestSmallerTower(vector<int>& arr)
{
    int n = arr.size();
    stack<int> pre, suf;
    vector<int> res(n, -1);
 
    // Make prefix stack
    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);
    }
 
    // Make suffix stack
    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;
}
 
// Driver code
int main()
{
 
    vector<int> arr = { 1, 3, 2 };
 
    // Function call
    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));
 
        // Make prefix stack
        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);
        }
 
        // Make suffix stack
        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);
 
        // Function call
        List<Integer> ans = nearestSmallerTower(arr);
        for (int it : ans) {
            System.out.print(it + " ");
        }
    }
}


Python3




# Python code of the above approach
# Function to find nearest smallest tower
def nearest_smaller_tower(arr):
    n = len(arr)
    pre = []  # Stack for previous towers
    suf = []  # Stack for next towers
    res = [-1] * # Initialize result array with -1
 
    # Make prefix stack
    for i in range(n):
        while pre and arr[pre[-1]] >= arr[i]:
            pre.pop()
 
        if pre:
            res[i] = pre[-1]
 
        pre.append(i)
 
    # Make suffix stack
    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
 
 
# Driver code
arr = [1, 3, 2]
 
# Function call
ans = nearest_smaller_tower(arr)
for it in ans:
    print(it, end=' ')


C#




using System;
 
public class TowerIndices
{
    // Method to find the indices of the smallest towers
    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;  // Index of the closest smaller tower
            int minDistance = int.MaxValue;  // Minimum distance to a smaller tower
 
            // Iterate over previous towers to find the closest smaller tower
            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);
         
        // Print the result for arr1
        Console.WriteLine("{" + string.Join(", ", result) + "}");
    }
}
// This code is contributed by Vikram_Shirsat


Javascript




// Function to find nearest smallest tower
function nearestSmallerTower(arr) {
    let n = arr.length;
    let pre = [];
    let suf = [];
    let res = new Array(n).fill(-1);
 
    // Make prefix stack
    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);
    }
 
    // Make suffix stack
    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;
}
 
// Test case
let arr = [1, 3, 2];
 
// Function call
let ans = nearestSmallerTower(arr);
for (let it of ans) {
    console.log(it + " ");
}


Output

-1 0 0 







Time Complexity: O(N+N) 
Auxiliary Space: O(N+N+N)  



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads