问题描述:
You have n coins and you want to build a staircase with these coins. The staircase consists of k rows where the ith row has exactly i coins. The last row of the staircase may be incomplete.
Given the integer n, return the number of complete rows of the staircase you will build.
解释说明:第一层摆1枚硬币,第二层摆2枚硬币,第i层摆i枚硬币,直到用完所有n枚硬币。(如果最后一层没有摆满,则不算最后一层)。求n枚硬币最多可以摆的层数。
限定条件:至少1枚,最多2,147,483,647枚。
思路分析:这是一道典型的二叉搜索题。搜索范围是1至65536,因为最多可以摆65536层(根据等差数列求和公式求项数)。
代码如下:
二叉搜索有不同的写法,原理其实相同,但细节之处(即临界符号)有明显不同,下面我提供两个不同版本的写法,供对比.
版本一:我最习惯用的版本
class Solution {
public int arrangeCoins(int n) {
//二叉搜索题目往往需要我们把参数设为更大的数据类型:长整型,以避免overflow
long left=1;
long right=65536;
//left=right的情况是临界情况,刚好可以不用考虑
while(left<right){
//mid必须用这种方法求,同理防止overflow
long mid=left+(right-left)/2;
//还不够大?左标设定在mid+1
if ((1+mid)*mid/2<n){
left=mid+1;
}
//刚好?就是它了
else if((1+mid)*mid/2==n){
return (int)mid;
}
//超了?右标设定在在mid
else{
right=mid;
}
}
//返回right-1是这道题目的具体情况,因为最后一排没摆满的不算
return (int)right-1;
}
}
版本二:我不太习惯的版本:
class Solution {
public int arrangeCoins(int n) {
long left=1;
long right=65536;
//把left=right的临界情况计算在内,这样最终的left可能在right的右侧
while(left<=right){
long mid=left+(right-left)/2;
//这一步与方法一相同
if ((1+mid)*mid/2<n){
left=mid+1;
}
//这一步与方法一相同
else if((1+mid)*mid/2==n){
return (int)mid;
}
//若超了,把right设定在mid-1
else{
right=mid-1;
}
}
return (int)right; //这里不用再-1
}
}
时间复杂度: O(logn)