题目描述
你总共有 n 枚硬币,并计划将它们按阶梯状排列。对于一个由 k 行组成的阶梯,其第 i 行必须正好有 i 枚硬币。阶梯的最后一行 可能 是不完整的。
给你一个数字 n ,计算并返回可形成 完整阶梯行 的总行数。
示例1:
输入: n = 5
输出: 2
解释: 因为第三行不完整,所以返回 2 。
示例2:
输入: n = 8
输出: 3
解释: 因为第四行不完整,所以返回 3 。
提示
- 1 < = n < = 2 31 − 1 1 <= n <= 2^{31} - 1 1<=n<=231−1
方法一:二分查找
解题思路
每一层硬币的数量逐层加 1,可构成首项为 1、公差为 1 的等差数列,利用等差数列的求和公式,可以求得前 k 个完整阶梯行所需的硬币数量为
k
∗
(
k
+
1
)
/
2
k * (k + 1) / 2
k∗(k+1)/2,因此可以利用二分查找来求得 n 个硬币最多可以构成的完整阶梯行的数量。
因为
1
<
=
n
<
=
2
31
−
1
1 <= n <= 2^{31} - 1
1<=n<=231−1,所以 n 枚硬币至少可以构成 1 个完整阶梯行,至多可以构成 n 个完整阶梯行。
代码
class Solution {
public:
int arrangeCoins(int n) {
// mid * (mid + 1) 会超出 int 表示范围,所以类型为 long long
long long l = 1, r = n, mid;
// 找出 n 个硬币最多可以构成的完整阶梯行的数量
while(l < r)
{
mid = (l + r + 1) >> 1;
if(mid * (mid + 1) / 2 <= n) l = mid;
else r = mid - 1;
}
return l;
}
};
复杂度分析
- 时间复杂度:O( l o g n logn logn)。
- 空间复杂度:O(1)。
方法二:数学解方程
解题思路
设可以构成的完整阶梯行的数量为 x 行,则有
(
x
+
1
)
∗
x
2
=
n
\frac{(x + 1) * x}{2} = n
2(x+1)∗x=n
整理得一元二次方程得,
x
2
+
x
−
2
n
=
0
x^2 + x - 2n = 0
x2+x−2n=0
因为 n >= 1,所以判别式
Δ
=
8
n
+
1
>
0
\Delta = 8n + 1 > 0
Δ=8n+1>0
解得
x
1
=
−
1
−
8
n
+
1
2
,
x
2
=
−
1
+
8
n
+
1
2
x_1 = \frac{-1 - \sqrt{8n + 1}}{2} ,x_2 = \frac{-1 + \sqrt{8n + 1}}{2}
x1=2−1−8n+1,x2=2−1+8n+1
因为至少能够构成 1 行完整阶梯行,所以负解舍去。
此时
⌊
x
2
⌋
\lfloor x_2 \rfloor
⌊x2⌋ 即为 n 枚硬币最多可以构成的完整阶梯行的数量。
代码
class Solution {
public:
int arrangeCoins(int n) {
return (int)((-1 + sqrt((long long)8 * n + 1)) / 2);
}
};
复杂度分析
sqrt 函数的时空复杂度与 CPU 支持的指令集相关。