排列硬币 arrange coins 三种解法详解

* 排列硬币
* https://leetcode-cn.com/problems/arranging-coins/description/
* 你总共有 n 枚硬币,你需要将它们摆成一个阶梯形状,第 k 行就必须正好有 k 枚硬币。

* 给定一个数字 n,找出可形成完整阶梯行的总行数。
* n 是一个非负整数,并且在32位有符号整型的范围内。
* 示例 1:
* n = 5
* 硬币可排列成以下几行:
* ¤
* ¤ ¤
* ¤ ¤
* 因为第三行不完整,所以返回2.

有三种解法,分别是暴力解法,二分查找,数学解法。时间复杂度分别是O(N),O(LogN),O(1)。

 

public class ArrangeCoins {
    //有三种解法
    //方法一,暴力法,时间复杂度为O(N),直接while循环,剩余值大于等于下一行行号
    public static int arrangeCoins1(int n) {
        if (n < 1) {
            return 0;
        }
        int rowNum = 1;
        int remain = n - rowNum;
        while (remain >= rowNum + 1) {//rowNum行有rowNum个硬币,所以remain值必须大于等于下一行rowNum+1
            rowNum++;//统计有效的rowNum
            remain = remain - rowNum;//更新剩余的值
        }
        return rowNum;
    }

    //方法二,二分查找法,时间复杂度O(LogN).思路就是找到一个k,使得所有和刚好大于n,那么k-1就是答案。这个假设是基于行号k=n。
    public static int arrangeCoins2(int n) {
        //公式 1+2+3+...+n = ((1+n)/2)*n,也就是首尾的均值乘以n等于和
        if(n == 1){
            return 1;
        }
        int left = 0;//从1开始
        int right = n;
        while (left <= right) {
            int mid = (left + right) / 2;
            //和
            long tmpSum = mid*(mid+1)/2;//实际等于mid*(mid+1)/2
            if (tmpSum < n) {
                left = mid + 1;
            } else {
                right = mid -1 ;
            }
        }
        return left - 1;//最后left就是mid,而这mid刚好就是让所有和大于n的存在,所以需要减去1
    }
    //方法三,就是数学方法
    //时间复杂度O(1),利用了等差数列的性质,等式n = (1 + x) * x / 2,
    //一元二次方程的求根公式 x = (-1 + sqrt(8 * n + 1)) / 2

    public static void main(String[] args) {
        System.out.println(arrangeCoins1(5));
        System.out.println(arrangeCoins2(5));
    }
}

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值