首先做题要看清楚题意。我最开始将行当成了列,看了半天没看明白怎么做。后来仔细读题看明白了后就写出了自己做的题解:
class Solution {
public int arrangeCoins(int n) {
if(n ==0){
return 0;
}
int res =0;
int i = 1;
while( i <= n){
n-=i;
res++;
i++;
}
return res;
}
}
实现很简单,就是通过依次减去该层需要的硬币数,直到减到0为止,并设置一个数用于记录是第几层。
我这个方法就是暴力破解,时间复杂度算是O(n)吧。
看了题解后直到了可以使用数学规律来结题,也可以使用二分法来快速实现。
数学法:高中的一元二次方程求解。
通过方程计算n枚硬币可以形成的完整的行阶数,设该数为x,则通过累加公式可以得到:
拆开后得到公式如下:
判别式:
求解得到:
去掉x1这个为负数的结果,结果就是x2向下取整的值。(结果有小数则说明还在填充下一行,但没满)
class Solution {
public int arrangeCoins(int n) {
return (int) ((Math.sqrt((long) 8 * n + 1) - 1) / 2);
}
}
二分法:
二分法同样要使用上面的公式:
假设生成的满阶数为x,那么就会满足上面的公式,我们就是通过上面的公式来进行筛选。
class Solution {
public int arrangeCoins(int n) {
long l = 1,r = n;
while(l <r){
long mid = l+r+1 >>1;
if(mid*(mid +1)/2 <= n){
l = mid;
}
else{
r = mid-1;
}
}
return (int)r;
}
}
学习的题解: