Find the maximum number of complete staircase rows that can be formed using binary search and triangular numbers.
Problem Restatement
We are given n coins.
We want to arrange them into a staircase shape.
The staircase must follow this rule:
| Row | Number of Coins |
|---|---|
| 1st row | 1 |
| 2nd row | 2 |
| 3rd row | 3 |
| … | … |
Each row must contain exactly one more coin than the previous row.
We need to return the number of complete rows that can be formed.
The last row may be incomplete, and incomplete rows do not count.
The official problem asks for the number of complete staircase rows that can be formed using exactly n coins. (leetcode.com)
Input and Output
| Item | Meaning |
|---|---|
| Input | Integer n |
| Output | Number of complete rows |
| Row sizes | 1, 2, 3, ... |
| Incomplete row | Does not count |
Example function shape:
def arrangeCoins(n: int) -> int:
...Examples
Example 1:
n = 5We build rows:
row 1 -> 1 coin
row 2 -> 2 coins
row 3 -> needs 3 coinsAfter the first two rows:
1 + 2 = 3We have:
5 - 3 = 2coins left, which is not enough for row 3.
So the answer is:
2Example 2:
n = 8We build:
1 + 2 + 3 = 6Two coins remain:
8 - 6 = 2which is not enough for row 4.
Answer:
3Example 3:
n = 1We can build one row:
1Answer:
1First Thought: Simulate Row by Row
We can repeatedly subtract row sizes.
Start with:
row = 1Then:
n -= row
row += 1until we cannot build the next row.
This works.
However, the problem has a direct mathematical structure.
Key Insight
To build k complete rows, we need:
1 + 2 + 3 + ... + kcoins.
This sum is the triangular number formula:
So we need the largest integer k such that:
This is a monotonic condition:
k | Coins Needed |
|---|---|
Larger k | Needs more coins |
Smaller k | Needs fewer coins |
Because the condition changes only once from true to false, binary search works perfectly.
Algorithm
Binary search on the answer.
The number of complete rows must lie between:
0 and nFor a candidate mid, compute:
If this value is less than or equal to n, then mid complete rows are possible.
Move right to search for a larger answer.
Otherwise, move left.
At the end, return the largest valid k.
Correctness
For any integer k, the number of coins required to build k complete rows is:
This value increases as k increases.
Therefore:
| Condition | Meaning |
|---|---|
required(k) <= n | k rows are possible |
required(k) > n | k rows are impossible |
So the set of valid k values forms a prefix:
valid, valid, valid, ..., invalid, invalidBinary search correctly finds the largest valid k.
Whenever the midpoint satisfies the inequality, the answer is at least that large, so searching right preserves correctness.
Whenever the midpoint fails the inequality, the answer must be smaller, so searching left preserves correctness.
When the search ends, the returned value is the maximum number of complete rows that can be formed.
Complexity
| Metric | Value | Why |
|---|---|---|
| Time | O(log n) | Binary search halves the range each step |
| Space | O(1) | Only a few variables are used |
Implementation
class Solution:
def arrangeCoins(self, n: int) -> int:
left = 0
right = n
while left <= right:
mid = (left + right) // 2
coins_needed = mid * (mid + 1) // 2
if coins_needed <= n:
left = mid + 1
else:
right = mid - 1
return rightCode Explanation
We search between:
left = 0
right = nThe midpoint candidate is:
mid = (left + right) // 2The number of coins needed for mid rows is:
implemented as:
coins_needed = mid * (mid + 1) // 2If enough coins exist:
if coins_needed <= n:then mid is valid, and we try larger values:
left = mid + 1Otherwise, mid is too large:
right = mid - 1When the loop finishes, right stores the largest valid row count.
Testing
def run_tests():
s = Solution()
assert s.arrangeCoins(1) == 1
assert s.arrangeCoins(5) == 2
assert s.arrangeCoins(8) == 3
assert s.arrangeCoins(3) == 2
assert s.arrangeCoins(6) == 3
assert s.arrangeCoins(10) == 4
assert s.arrangeCoins(0) == 0
assert s.arrangeCoins(2147483647) == 65535
print("all tests passed")
run_tests()Test meaning:
| Test | Why |
|---|---|
1 | Smallest non-zero case |
5 | Incomplete third row |
8 | Standard example |
3 | Exact triangular number |
6 | Exact larger triangular number |
10 | Another exact staircase |
0 | No coins |
| Large input | Checks overflow safety and efficiency |