Easy草稿★★★★★O(log n) 時間 · O(1) 空間
Binary SearchMath
Patterns🎯 二分搜尋🧮 數學・組合
尚未複習過

解法已隱藏 — 先讀題目敘述、自己想想看,再點上方按鈕揭曉。

441Arranging CoinsBinary SearchEasyBinary Search

你有 n 枚硬幣,想排成階梯形。第 k 行必須恰好有 k 枚硬幣。回傳可以完整填滿的行數。

Example:

Input: n = 8 Output: 3(第 1 行 1 枚 + 第 2 行 2 枚 + 第 3 行 3 枚 = 6,剩 2 枚不夠填第 4 行)

Intuition

TIP

找最大的 k 使得 k*(k+1)/2 <= n,可以用二分搜尋或數學公式。

Approaches

1. Simulation — O(sqrt(n)) / O(1)
  • Idea: 逐行扣除硬幣直到不夠為止
  • Time: O(sqrt(n))
  • Space: O(1)
Simulation Code
class Solution {
    fun arrangeCoins(n: Int): Int {
        var remaining = n
        var row = 0
        while (remaining > row) {
            row++
            remaining -= row
        }
        return row
    }
}
⭐ 2. Binary Search — O(log n) / O(1)
  • Idea: 在 [1, n] 上二分搜尋最大的 k 使得 k*(k+1)/2 <= n
  • Time: O(log n)
  • Space: O(1)
class Solution {
    fun arrangeCoins(n: Int): Int {
        var left = 1L
        var right = n.toLong()
        while (left < right) {
            val mid = left + (right - left + 1) / 2
            if (mid * (mid + 1) / 2 <= n) {
                left = mid
            } else {
                right = mid - 1
            }
        }
        return left.toInt()
    }
}

WARNING

注意使用 Long 避免 mid * (mid + 1) 溢位。這是找最大可行值,所以用 left = mid 配合 mid = left + (right - left + 1) / 2 避免無限迴圈。

3. Math Formula — O(1) / O(1)
  • Idea: 解二次方程式 k*(k+1)/2 = n,得 k = (-1 + sqrt(1 + 8n)) / 2
  • Time: O(1)
  • Space: O(1)
Math Formula Code
class Solution {
    fun arrangeCoins(n: Int): Int {
        return ((-1.0 + Math.sqrt(1.0 + 8.0 * n)) / 2.0).toInt()
    }
}

🔑 Takeaways