leetcode-441. 排列硬币

151 阅读2分钟
/**
 * 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;
    }
}