/**
* ref:https://leetcode-cn.com/problems/arranging-coins/
* 你总共有n枚硬币,并计划将它们按阶梯状排列。对于一个由k行组成的阶梯,其第i行必须正好有i枚硬币。
* 阶梯的最后一行可能是不完整的。给你一个数字n,计算并返回可形成完整阶梯行的总行数。
* 输入:n = 5
* 输出:2
* 解释:因为第三行不完整,所以返回2。
**/
public class ArrangingCoins {
public static void main(String[] args){
System.out.println(forceArranging(22));
System.out.println(binaryArranging(21));
}
/**
* 暴力破解
* 假设有x个硬币的话,最多可以摆放x行。则迭代x次。
* 每迭代一次,计算剩余的硬币数,并判断剩余的硬币数是否满足下一次摆放数。
* 当剩余硬币数比当前迭代行数小时,则证明下一行是无法摆满,直接结束。
*/
public static int forceArranging(int x){
// 一共有x个硬币,那么最多可以摆放i行.i的值最大是x
// 只有一个硬币时,只可以摆放1行。
for(int i=1;i<=x;i++){
// 扣除当前行需要的硬币数
x -=i;
// 判断是否满足下一行硬币数,不足则结束
if(x<(i+1)){
return i;
}
}
return -1;
}
/**
* 二分法解决:假设有x个硬币的话,最多可以摆放x行。
* 则每定义两个常量,来定义最少可以摆放0行,最多可以摆放x行,然后计算中值所需要的硬币数,
* 如果需要硬币数大于传入的值,则将最多行数改为中值-1进行再次比较。
* 如果需要硬币数小于传入的值,则将最少行数改为中值+1进行再次比较。
*/
public static int binaryArranging(int x){
// 最少摆放0行
int left = 0;
// 最多摆放x行
int right = x;
// 当最好和最多行数重叠时,结束
while(left<=right){
// 中间行数
int mid = left+(right-left)/2;
// 计算需要的硬币数
int coins = (mid*(mid+1))/2;
if(x==coins){
return mid;
}else if(x<coins){
right = mid-1;
}else{
left = mid+1;
}
}
return right;
}
}