1. 问题背景与理解
这道排列硬币的题目看似简单,却蕴含着巧妙的算法思维。题目要求我们找到可以形成完整阶梯排列的硬币行数,其中第k行恰好有k枚硬币。比如当n=5时,可以排列成2行完整阶梯(第一行1枚,第二行2枚,剩余2枚不足以构成第三行)。
这类问题在实际开发中其实很常见,比如资源分配、任务调度等场景都需要类似的计算。我最近在开发一个分布式任务队列时,就遇到过需要类似阶梯分配的计算需求。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 暴力解法分析
最直观的解法就是从第一行开始逐行累加,直到超过总硬币数:
python复制def arrangeCoins(n):
k = 0
total = 0
while total <= n:
k += 1
total += k
return k - 1
这种方法的时间复杂度是O(n),当n很大时(比如2^31-1)效率会很低。我在第一次尝试时就用了这个方法,结果在测试用例n=2147483647时直接超时了。
3. 数学公式优化
其实这个问题可以用数学公式来解决。完整的k行阶梯需要的硬币总数是k*(k+1)/2。我们可以解这个不等式:
k*(k+1)/2 ≤ n
解这个二次方程可以得到k的近似值。代码实现如下:
python复制import math
def arrangeCoins(n):
return int((math.sqrt(8*n + 1) - 1)/2)
这种方法的时间复杂度是O(1),非常高效。但要注意浮点数精度问题,特别是在处理大数时。我在实际测试中发现,当n接近2^31-1时,计算结果会出现偏差。
4. 二分法详细解析
二分法才是这个问题的最佳解法。我们可以把问题转化为在1到n之间寻找最大的k,使得k*(k+1)/2 ≤ n。
4.1 二分法实现
python复制def arrangeCoins(n):
left, right = 1, n
while left <= right:
mid = left + (right - left) // 2
total = mid * (mid + 1) // 2
if total =
