questions B (backspace - burst-balloons)
This commit is contained in:
204
backend/data/questions/building-boxes.yaml
Normal file
204
backend/data/questions/building-boxes.yaml
Normal file
@@ -0,0 +1,204 @@
|
||||
title: Building Boxes
|
||||
slug: building-boxes
|
||||
difficulty: hard
|
||||
leetcode_id: 1739
|
||||
leetcode_url: https://leetcode.com/problems/building-boxes/
|
||||
categories:
|
||||
- math
|
||||
- binary-search
|
||||
patterns:
|
||||
- binary-search
|
||||
- greedy
|
||||
|
||||
description: |
|
||||
You have a cubic storeroom where the width, length, and height of the room are all equal to `n` units. You are asked to place `n` boxes in this room where each box is a cube of unit side length. There are however some rules to placing the boxes:
|
||||
|
||||
- You can place the boxes anywhere on the floor.
|
||||
- If box `x` is placed on top of box `y`, then each side of the four vertical sides of box `y` **must** either be adjacent to another box or to a wall.
|
||||
|
||||
Given an integer `n`, return *the **minimum** possible number of boxes touching the floor*.
|
||||
|
||||
constraints: |
|
||||
- `1 <= n <= 10^9`
|
||||
|
||||
examples:
|
||||
- input: "n = 3"
|
||||
output: "3"
|
||||
explanation: "Place three boxes in the corner of the room, all touching the floor."
|
||||
- input: "n = 4"
|
||||
output: "3"
|
||||
explanation: "Place three boxes on the floor in the corner, with one box stacked on top of a corner box (which has all four sides supported by walls/boxes)."
|
||||
- input: "n = 10"
|
||||
output: "6"
|
||||
explanation: "Place boxes in a stepped pyramid pattern in the corner. Six boxes touch the floor, supporting four more boxes above them."
|
||||
|
||||
explanation:
|
||||
intuition: |
|
||||
Imagine you're stacking boxes in the corner of a room. The corner is special because it provides two walls as support. A box can only support another box on top if all four of its vertical sides are covered — either by walls or other boxes.
|
||||
|
||||
Think of it like building a **stepped pyramid** in a corner. The optimal strategy is to build "layers" where:
|
||||
- Layer 1 (bottom floor): boxes form a triangular staircase pattern in the corner
|
||||
- Layer 2: boxes sit on top of layer 1, also forming a smaller triangle
|
||||
- And so on...
|
||||
|
||||
The key insight is recognising that a complete pyramid of height `h` has:
|
||||
- **Floor boxes**: `1 + 2 + 3 + ... + h = h(h+1)/2` (triangular number)
|
||||
- **Total boxes**: `1 + 3 + 6 + ... + h(h+1)/2` (sum of triangular numbers = tetrahedral number)
|
||||
|
||||
The total boxes in a complete pyramid is `h(h+1)(h+2)/6` — this is the h<sup>th</sup> **tetrahedral number**.
|
||||
|
||||
Our strategy: find the largest complete pyramid that fits within `n` boxes, then add floor boxes one-by-one until we can fit all `n` boxes. Each additional floor box lets us stack a "column" of boxes on top of the existing structure.
|
||||
|
||||
approach: |
|
||||
We solve this using **Mathematical Analysis + Greedy Addition**:
|
||||
|
||||
**Step 1: Find the largest complete pyramid**
|
||||
|
||||
- A complete pyramid of height `h` contains `h(h+1)(h+2)/6` total boxes
|
||||
- Use binary search or iteration to find the largest `h` where this formula gives `<= n`
|
||||
- Let `total` be the number of boxes in this complete pyramid
|
||||
- Let `floor` be the floor boxes in this pyramid: `h(h+1)/2`
|
||||
|
||||
|
||||
|
||||
**Step 2: Handle remaining boxes**
|
||||
|
||||
- Calculate `remaining = n - total` (boxes left to place)
|
||||
- If `remaining == 0`, return `floor`
|
||||
|
||||
|
||||
|
||||
**Step 3: Add floor boxes one at a time**
|
||||
|
||||
- Each new floor box at position `k` allows us to place `k` additional boxes (a column of height `k`)
|
||||
- Add floor boxes with `k = 1, 2, 3, ...` until the cumulative column heights cover `remaining`
|
||||
- This is because the k<sup>th</sup> additional floor box can support a column of `k` boxes above it
|
||||
|
||||
|
||||
|
||||
**Step 4: Return the total floor boxes**
|
||||
|
||||
- Return `floor + (number of additional floor boxes needed)`
|
||||
|
||||
|
||||
|
||||
The greedy addition works because adding floor boxes in order (1, 2, 3, ...) maximises the boxes we can stack per floor box added.
|
||||
|
||||
common_pitfalls:
|
||||
- title: Ignoring the Corner Constraint
|
||||
description: |
|
||||
Without using the corner, you'd need far more floor boxes. The corner provides two walls, meaning boxes placed against both walls can immediately support boxes on top.
|
||||
|
||||
The optimal solution always uses the corner to minimise floor contact.
|
||||
wrong_approach: "Placing boxes in the middle of the room"
|
||||
correct_approach: "Build a pyramid in the corner using wall support"
|
||||
|
||||
- title: Integer Overflow with Large n
|
||||
description: |
|
||||
With `n` up to `10^9`, computing `h(h+1)(h+2)` can overflow 32-bit integers. In Python this isn't an issue, but in other languages you need to use 64-bit integers or be careful with the order of operations.
|
||||
|
||||
Also, the maximum pyramid height for `n = 10^9` is around 1817, so iteration is feasible.
|
||||
wrong_approach: "Using 32-bit integers for intermediate calculations"
|
||||
correct_approach: "Use 64-bit integers or Python's arbitrary precision"
|
||||
|
||||
- title: Off-by-One in Additional Boxes
|
||||
description: |
|
||||
When adding floor boxes after a complete pyramid, the k<sup>th</sup> additional floor box supports a column of `k` boxes (including itself as the base counted towards remaining). Be careful about whether you're counting the floor box itself.
|
||||
|
||||
The cumulative sum `1 + 2 + ... + k = k(k+1)/2` should cover `remaining`.
|
||||
wrong_approach: "Miscounting how many boxes each floor box supports"
|
||||
correct_approach: "The k-th new floor box adds capacity for k boxes total"
|
||||
|
||||
key_takeaways:
|
||||
- "**Triangular and tetrahedral numbers**: Complete pyramids follow `h(h+1)(h+2)/6` — recognising this pattern is key"
|
||||
- "**Greedy completion**: After the largest complete pyramid, add floor boxes greedily to cover remaining capacity"
|
||||
- "**Geometric reasoning**: Visualising 3D stacking as layered 2D triangles simplifies the math"
|
||||
- "**Binary search for inverse functions**: Finding the largest `h` where `f(h) <= n` is a classic binary search application"
|
||||
|
||||
time_complexity: "O(n^(1/3)). The pyramid height h is proportional to the cube root of n, and we iterate up to h steps."
|
||||
space_complexity: "O(1). Only a few variables for tracking the pyramid dimensions and remaining boxes."
|
||||
|
||||
solutions:
|
||||
- approach_name: Mathematical Analysis
|
||||
is_optimal: true
|
||||
code: |
|
||||
def minimum_boxes(n: int) -> int:
|
||||
# Step 1: Find the largest complete pyramid height
|
||||
# Tetrahedral number: h(h+1)(h+2)/6
|
||||
h = 0
|
||||
total = 0 # Total boxes in complete pyramid
|
||||
floor = 0 # Floor boxes in complete pyramid
|
||||
|
||||
# Build complete layers until we exceed n
|
||||
while total + (h + 1) * (h + 2) // 2 <= n:
|
||||
h += 1
|
||||
# Add triangular number h(h+1)/2 to floor
|
||||
floor += h
|
||||
# Total boxes = sum of triangular numbers = h(h+1)(h+2)/6
|
||||
total += h * (h + 1) // 2
|
||||
|
||||
# Step 2: Add individual floor boxes for remaining capacity
|
||||
remaining = n - total
|
||||
extra_floor = 0
|
||||
capacity = 0 # How many boxes we can add with extra floor boxes
|
||||
|
||||
# Each new floor box k allows stacking k boxes
|
||||
while capacity < remaining:
|
||||
extra_floor += 1
|
||||
capacity += extra_floor # The k-th floor box adds k capacity
|
||||
|
||||
return floor + extra_floor
|
||||
explanation: |
|
||||
**Time Complexity:** O(n^(1/3)) — The pyramid height is O(n^(1/3)), and we iterate through layers and additional floor boxes.
|
||||
|
||||
**Space Complexity:** O(1) — Only constant extra space for variables.
|
||||
|
||||
We first build the largest complete pyramid possible (where each layer is a triangular arrangement). Then we greedily add floor boxes one by one. Each additional floor box at position k lets us add a column of k boxes. We stop when we have enough capacity for all n boxes.
|
||||
|
||||
- approach_name: Binary Search
|
||||
is_optimal: false
|
||||
code: |
|
||||
def minimum_boxes(n: int) -> int:
|
||||
# Binary search for the largest complete pyramid height
|
||||
def tetrahedral(h: int) -> int:
|
||||
"""Total boxes in a complete pyramid of height h."""
|
||||
return h * (h + 1) * (h + 2) // 6
|
||||
|
||||
def triangular(k: int) -> int:
|
||||
"""k-th triangular number."""
|
||||
return k * (k + 1) // 2
|
||||
|
||||
# Find largest h where tetrahedral(h) <= n
|
||||
lo, hi = 0, 2000 # Max h for n=10^9 is ~1817
|
||||
while lo < hi:
|
||||
mid = (lo + hi + 1) // 2
|
||||
if tetrahedral(mid) <= n:
|
||||
lo = mid
|
||||
else:
|
||||
hi = mid - 1
|
||||
|
||||
h = lo
|
||||
total = tetrahedral(h)
|
||||
floor = triangular(h)
|
||||
remaining = n - total
|
||||
|
||||
if remaining == 0:
|
||||
return floor
|
||||
|
||||
# Binary search for minimum extra floor boxes needed
|
||||
# k extra floor boxes give capacity 1+2+...+k = k(k+1)/2
|
||||
lo, hi = 1, 2000
|
||||
while lo < hi:
|
||||
mid = (lo + hi) // 2
|
||||
if triangular(mid) >= remaining:
|
||||
hi = mid
|
||||
else:
|
||||
lo = mid + 1
|
||||
|
||||
return floor + lo
|
||||
explanation: |
|
||||
**Time Complexity:** O(log n) — Two binary searches with O(log(n^(1/3))) = O(log n) complexity.
|
||||
|
||||
**Space Complexity:** O(1) — Only constant extra space.
|
||||
|
||||
This approach uses binary search twice: first to find the largest complete pyramid, then to find the minimum additional floor boxes needed. While asymptotically faster, the constants are similar since n^(1/3) for n=10^9 is only ~1000. The iterative approach is often clearer and equally fast in practice.
|
||||
Reference in New Issue
Block a user