Talentd
FleetCode
Make and follow sheets.Sign in

Maximum Building Height solution and explanation

HardArrayMathSorting7 min read67.1% acceptanceUpdated 9 Apr 2026
Maximum Building Height | Detailed For Beginners | Dry Runs | Leetcode 1840 | codestorywithMIKcodestorywithMIK · 1:01:53 · 8K viewsWatch on YouTube
9 more videos on this problem
  1. Maximum Building Height | Detailed For Beginners | Dry Runs | Leetcode 1840 | codestorywithMIKcodestorywithMIK · 1:01:53 · 8K views
  2. Maximum Building Height | Leetcode - 1840Shivam Gupta · 30:54 · 2K views
  3. LeetCode 1840. Maximum Building HeightHappy Coding · 23:53 · 2K views
  4. 1840. Maximum Building Height | Leetcode Daily - PythonLeetcode Daily · 4:55 · 1K views
  5. Maximum Building Height | LeetCode 1840Aman Anand · 17:07 · 1K views
  6. leetcode 1840 |Maximum Building Height | Leetcode POTD | Math | Sorting| DSACode With Vick · 29:02 · 1K views
  7. Maximum Building Height 🔥 Leetcode 1840 | Interview Level Problem | Dry run Study Placement · 46:15 · 1K views
  8. Maximum Building Height | LeetCode 1840 - Pythonimpoldev · 10:40 · 699 views
  9. 1840. Maximum Building Height (Leetcode Hard)Programming Live with Larry · 50:22 · 620 views
  10. Daily Leetcode #2272: Jun 20, 2026 - 1840. Maximum Building HeightProgramming Live with Larry · 35:13 · 559 views

The problem

You want to build n new buildings in a city. The new buildings will be built in a line and are labeled from 1 to n.

However, there are city restrictions on the heights of the new buildings:

  • The height of each building must be a non-negative integer.
  • The height of the first building must be 0.
  • The height difference between any two adjacent buildings cannot exceed 1.

Additionally, there are city restrictions on the maximum height of specific buildings. These restrictions are given as a 2D integer array restrictions where restrictions[i] = [idi, maxHeighti] indicates that building idi must have a height less than or equal to maxHeighti.

It is guaranteed that each building will appear at most once in restrictions, and building 1 will not be in restrictions.

Return the maximum possible height of the tallest building.

Example 1:

Input: n = 5, restrictions = [[2,1],[4,1]]
Output: 2
Explanation: The green area in the image indicates the maximum allowed height for each building.
We can build the buildings with heights [0,1,2,1,2], and the tallest building has a height of 2.

Example 2:

Input: n = 6, restrictions = []
Output: 5
Explanation: The green area in the image indicates the maximum allowed height for each building.
We can build the buildings with heights [0,1,2,3,4,5], and the tallest building has a height of 5.

Example 3:

Input: n = 10, restrictions = [[5,3],[2,5],[7,4],[10,3]]
Output: 5
Explanation: The green area in the image indicates the maximum allowed height for each building.
We can build the buildings with heights [0,1,2,3,3,4,4,5,4,3], and the tallest building has a height of 5.

Constraints:

  • 2 <= n <= 109
  • 0 <= restrictions.length <= min(n - 1, 105)
  • 2 <= idi <= n
  • idi is unique.
  • 0 <= maxHeighti <= 109

Approach overview

Problem Overview: You are given n buildings in a row where adjacent buildings can differ in height by at most 1. Some buildings also have maximum height restrictions. The task is to determine the highest possible building that can exist while satisfying all restrictions.

Approach 1: Divide and Conquer Approach (O(m log m) time, O(m) space)

This strategy treats the restrictions as boundary constraints and recursively evaluates the maximum possible peak between them. First, sort the restriction list by building index and add implicit constraints such as building 1 with height 0. During recursion, split the range between two restriction points and compute the highest peak allowed using the slope constraint |h[i] - h[i-1]| ≤ 1. The midpoint height is limited by both boundaries, so the peak becomes (leftHeight + rightHeight + distance) / 2. Recursively evaluating segments ensures the height never violates neighboring limits. Time complexity is O(m log m) due to sorting and divide steps, while auxiliary recursion storage uses O(m) space. This approach highlights the mathematical structure of the problem and works well when reasoning about independent segments.

Approach 2: Iterative In-Place Sorting (O(m log m) time, O(1) extra space)

The practical solution most engineers implement starts by sorting restrictions by building index. Add a base restriction (1, 0) and optionally (n, n-1) to cap the final building. Then perform two constraint passes. The left-to-right pass ensures every restriction respects the maximum slope from the previous one: h[i] = min(h[i], h[i-1] + distance). The right-to-left pass enforces the same constraint from the opposite direction. After normalization, each pair of adjacent restrictions defines a segment where the height increases then decreases like a pyramid. The highest peak between them is computed using the same midpoint formula based on distance and boundary heights. Iterate through all segments and track the maximum. Sorting dominates the complexity at O(m log m), and the algorithm runs in O(1) additional space when updates are done in place.

Both solutions rely heavily on reasoning about ordered constraints, which is why understanding sorting and boundary propagation in arrays is critical. The peak calculation itself comes from simple math around linear growth and symmetric slopes.

Recommended for interviews: The iterative sorted approach is what most interviewers expect. It shows you can normalize constraints with forward and backward passes and derive the peak mathematically. Mentioning a divide-and-conquer perspective demonstrates deeper understanding, but the sorted propagation solution is simpler to implement and easier to reason about under interview pressure.

Approach 1: Divide and Conquer Approach

This approach involves breaking down the problem into smaller subproblems, solving each subproblem independently, and then combining their results to solve the original problem. It is particularly useful when the problem has a recursive subproblem structure.

def merge_sort(arr):
    if len(arr) > 1:
        mid = len(arr) // 2
        L = arr[:mid]
        R = arr[mid:]

        merge_sort(L)
        merge_sort(R)

        i = j = k = 0

        while i < len(L) and j < len(R):
            if L[i] < R[j]:
                arr[k] = L[i]
                i += 1
            else:
                arr[k] = R[j]
                j += 1
            k += 1

        while i < len(L):
            arr[k] = L[i]
            i += 1
            k += 1

        while j < len(R):
            arr[k] = R[j]
            j += 1
            k += 1

arr = [12, 11, 13, 5, 6, 7]
merge_sort(arr)
print("Sorted array is:", arr)
#include <stdio.h>

void merge(int arr[], int l, int m, int r) {
    int n1 = m - l + 1;
    int n2 = r - m;
    int L[n1], R[n2];
    for (int i = 0; i < n1; i++)
        L[i] = arr[l + i];
    for (int j = 0; j < n2; j++)
        R[j] = arr[m + 1 + j];

    int i = 0, j = 0, k = l;
    while (i < n1 && j < n2) {
        if (L[i] <= R[j]) {
            arr[k] = L[i];
            i++;
        } else {
            arr[k] = R[j];
            j++;
        }
        k++;
    }

    while (i < n1) {
        arr[k] = L[i];
        i++; k++;
    }

    while (j < n2) {
        arr[k] = R[j];
        j++; k++;
    }
}

void mergeSort(int arr[], int l, int r) {
    if (l < r) {
        int m = l + (r - l) / 2;
        mergeSort(arr, l, m);
        mergeSort(arr, m + 1, r);
        merge(arr, l, m, r);
    }
}

int main() {
    int arr[] = {12, 11, 13, 5, 6, 7};
    int arr_size = sizeof(arr) / sizeof(arr[0]);

    mergeSort(arr, 0, arr_size - 1);

    printf("Sorted array is: \n");
    for (int i = 0; i < arr_size; i++)
        printf("%d ", arr[i]);
    return 0;
}

The Python solution recursively divides the array and uses helper arrays to merge sorted halves. It manipulates the array in place to achieve the sorting.

Complexity

Time Complexity: O(n log n) due to recursive division and merging of parts.
Space Complexity: O(n) for the auxiliary arrays used during merging.

Try this approach in the editor

Approach 2: Iterative In-Place Sorting

This approach involves using an iterative sorting algorithm that operates directly on the array without requiring additional auxiliary space. The Insertion Sort algorithm is a classic example of such an algorithm.

class InsertionSort {
    void sort(int arr[]) {
        int n = arr.length;
        for (int i = 1; i < n; ++i) {
            int key = arr[i];
            int j = i - 1;

            while (j >= 0 && arr[j] > key) {
                arr[j + 1] = arr[j];
                j = j - 1;
            }
            arr[j + 1] = key;
        }
    }

    public static void main(String args[]) {
        int arr[] = {12, 11, 13, 5, 6};

        InsertionSort ob = new InsertionSort();
        ob.sort(arr);

        System.out.println("Sorted array is");
        for (int i = 0; i < arr.length; ++i)
            System.out.print(arr[i] + " ");
    }
}
function insertionSort(arr) {
    for (let i = 1; i < arr.length; i++) {
        let key = arr[i];
        let j = i - 1;

        while (j >= 0 && arr[j] > key) {
            arr[j + 1] = arr[j];
            j = j - 1;
        }
        arr[j + 1] = key;
    }
}

let arr = [12, 11, 13, 5, 6];
insertionSort(arr);
console.log("Sorted array is:", arr);

The Java implementation follows the same logic as JavaScript: it maintains a sorted sub-array and inserts new elements into their correct positions within this sub-array, right from the first element to the last.

Complexity

Time Complexity: O(n^2) in the average and worst case scenarios.
Space Complexity: O(1) as it sorts in place.

Try this approach in the editor

Approach 3: Sorting + Mathematics

First, we sort all the constraints by the building number in ascending order.

Then we traverse all the constraints from left to right. For each constraint, we can get an upper bound on the maximum height, i.e., r_i[1] = min(r_i[1], r_{i-1}[1] + r_i[0] - r_{i-1}[0]), where r_i represents the i-th constraint, and r_i[0] and r_i[1] represent the building number and the upper bound on the maximum height of the building, respectively.

Next, we traverse all the constraints from right to left. For each constraint, we can get an upper bound on the maximum height, i.e., r_i[1] = min(r_i[1], r_{i+1}[1] + r_{i+1}[0] - r_i[0]).

In this way, we obtain the upper bound on the maximum height for each constrained building.

The problem asks for the height of the tallest building. We can enumerate the buildings between two adjacent constraints i and i+1. To maximize the height, the height should first increase and then decrease. Suppose the maximum height is t, then t - r_i[1] + t - r_{i+1}[1] leq r_{i+1}[0] - r_i[0], i.e., t leq \frac{r_i[1] + r_{i+1}[1] + r_{i+1}[0] - r_{i}[0]}{2}. We take the maximum value of all such t.

The time complexity is O(m times log m), and the space complexity is O(m). Here, m is the number of constraints.

class Solution {
public:
    int maxBuilding(int n, vector<vector<int>>& restrictions) {
        auto&& r = restrictions;
        r.push_back({1, 0});
        ranges::sort(r);
        if (r[r.size() - 1][0] != n) {
            r.push_back({n, n - 1});
        }
        int m = r.size();
        for (int i = 1; i < m; ++i) {
            r[i][1] = min(r[i][1], r[i - 1][1] + r[i][0] - r[i - 1][0]);
        }
        for (int i = m - 2; i > 0; --i) {
            r[i][1] = min(r[i][1], r[i + 1][1] + r[i + 1][0] - r[i][0]);
        }
        int ans = 0;
        for (int i = 0; i < m - 1; ++i) {
            int t = (r[i][1] + r[i + 1][1] + r[i + 1][0] - r[i][0]) / 2;
            ans = max(ans, t);
        }
        return ans;
    }
};
function maxBuilding(n: number, restrictions: number[][]): number {
    restrictions.push([1, 0]);
    restrictions.sort((a, b) => a[0] - b[0]);
    if (restrictions[restrictions.length - 1][0] !== n) {
        restrictions.push([n, n - 1]);
    }

    const m = restrictions.length;
    for (let i = 1; i < m; ++i) {
        restrictions[i][1] = Math.min(
            restrictions[i][1],
            restrictions[i - 1][1] + restrictions[i][0] - restrictions[i - 1][0],
        );
    }

    for (let i = m - 2; i >= 0; --i) {
        restrictions[i][1] = Math.min(
            restrictions[i][1],
            restrictions[i + 1][1] + restrictions[i + 1][0] - restrictions[i][0],
        );
    }

    let ans = 0;
    for (let i = 0; i < m - 1; ++i) {
        const t = Math.floor(
            (restrictions[i][1] +
                restrictions[i + 1][1] +
                restrictions[i + 1][0] -
                restrictions[i][0]) /
                2,
        );
        ans = Math.max(ans, t);
    }

    return ans;
}
func maxBuilding(n int, restrictions [][]int) (ans int) {
	r := restrictions
	r = append(r, []int{1, 0})
	sort.Slice(r, func(i, j int) bool { return r[i][0] < r[j][0] })
	if r[len(r)-1][0] != n {
		r = append(r, []int{n, n - 1})
	}
	m := len(r)
	for i := 1; i < m; i++ {
		r[i][1] = min(r[i][1], r[i-1][1]+r[i][0]-r[i-1][0])
	}
	for i := m - 2; i > 0; i-- {
		r[i][1] = min(r[i][1], r[i+1][1]+r[i+1][0]-r[i][0])
	}
	for i := 0; i < m-1; i++ {
		t := (r[i][1] + r[i+1][1] + r[i+1][0] - r[i][0]) / 2
		ans = max(ans, t)
	}
	return ans
}
Try this approach in the editor

Complexity comparison

ApproachComplexity
Divide and Conquer Approach

Time Complexity: O(n log n) due to recursive division and merging of parts.
Space Complexity: O(n) for the auxiliary arrays used during merging.

Iterative In-Place Sorting

Time Complexity: O(n^2) in the average and worst case scenarios.
Space Complexity: O(1) as it sorts in place.

Sorting + Mathematics–

Complexity analysis

ApproachTimeSpaceWhen to Use
Divide and ConquerO(m log m)O(m)Useful when reasoning about independent segments and recursive constraint splitting
Iterative In-Place Sorting with Constraint PropagationO(m log m)O(1)Best general solution; easy to implement and commonly expected in interviews

Frequently asked questions

Is Maximum Building Height easy or hard?

Maximum Building Height is classified as a Hard problem on LeetCode. The difficulty comes from recognizing that restrictions must be normalized first and that the maximum height appears between restriction boundaries rather than at the restricted buildings themselves.

Maximum Building Height Python/Java solution

Python and Java implementations typically follow the same pattern: sort the restrictions, add boundary constraints, run two passes to enforce slope limits, and then compute the maximum peak between consecutive restrictions. The logic remains identical across languages with O(m log m) time complexity.

How to solve Maximum Building Height in O(n)?

A strictly O(n) solution is not typical because restrictions must be processed in sorted order of building index. However, once the restrictions are sorted, all constraint propagation and peak calculations run in linear time. The main idea is to enforce slope limits in two passes and then compute the highest possible midpoint between each pair of restrictions.

What is the best approach for Maximum Building Height?

The most practical solution sorts all building restrictions and then propagates height constraints from left-to-right and right-to-left. After normalization, each adjacent restriction pair defines a segment where the maximum peak can be computed mathematically. This approach runs in O(m log m) time due to sorting and uses constant extra space.

Is Maximum Building Height asked at Google/Amazon/Meta?

Hard array and constraint-propagation problems like Maximum Building Height frequently appear in interviews at companies such as Google, Amazon, and Meta. They test reasoning about constraints, mathematical bounds, and careful iteration across sorted data.

What data structure is used in Maximum Building Height?

The core data structure is an array or list of restriction pairs. After sorting by building index, the algorithm iterates through the array to enforce height limits and compute segment peaks. No advanced structures like heaps or trees are required.

What is the time complexity of Maximum Building Height?

The optimal solution runs in O(m log m) time where m is the number of restrictions. Sorting the restriction list dominates the runtime, while the forward pass, backward pass, and peak calculations are all linear. Space complexity can be reduced to O(1) if updates are done in place.

Comments

Now write it yourselfClose this page and solve Maximum Building Height in the editor, without looking.
Practise Maximum Building Height