LeetCode | 441 | 排列硬币 | 二分查找

🙋大家好!我是毛毛张!
🌈个人首页: 神马都会亿点点的毛毛张

今天分享的是LeetCode中一道标签为简单的算法题,本质是一道数学题


LeetCode链接:441. 排列硬币

1.题目描述

你总共有 n 枚硬币,并计划将它们按阶梯状排列。对于一个由 k 行组成的阶梯,其第 i 行必须正好有 i 枚硬币。阶梯的最后一行 可能 是不完整的。

给你一个数字 n ,计算并返回可形成 完整阶梯行 的总行数。

示例 1:

img

输入:n = 5
输出:2
解释:因为第三行不完整,所以返回 2 。

示例 2:

img

输入:n = 8
输出:3
解释:因为第四行不完整,所以返回 3 。

提示:

  • 1 < = n < = 2 31 − 1 1 <= n <= 2^{31} - 1 1<=n<=2311

2.题解

2.1 公式解法

class Solution {
    public int arrangeCoins(int n) {
        // 使用数学公式求解排列硬币问题
        // 使用 long 类型防止溢出
        long num = (long) n;

        // 计算公式:
        // 完整行数 k 满足的方程:k * (k + 1) / 2 <= n
        // 变形成:k^2 + k <= 2 * n
        // 转化为求解 k 的公式:k = (sqrt(8 * n + 1) - 1) / 2

        // 计算 k 的值,并将结果转换为 int 类型返回
        return (int) ((Math.sqrt(8 * num + 1) - 1) / 2);
    }
}

2.2 暴力解法

class Solution {
    public int arrangeCoins(int n) {
        // 初始化变量i为0,用于表示行数
        int i = 0;
        // 循环判断能够放多少行完整的硬币
        while (i <= n) {
            // 增加行数
            i++;
            // 计算当前行数需要的硬币总数,使用long类型防止溢出
            long coins = (long) i * (1 + i) / 2;
            // 如果当前行数需要的硬币总数大于n,退出循环
            if (coins > n) break;
        }
        // 返回完整行数的数量
        return i - 1;
    }
}

2.3 二分查找

class Solution {
    public int arrangeCoins(int n) {
        // 初始化二分查找的左边界和右边界
        int left = 1, right = n;

        // 使用二分查找寻找最大完整行数
        while (left <= right) {
            // 计算中间位置,防止整型溢出
            int mid = left + (right - left) / 2;

            // 计算当前中间位置能放的硬币总数,使用 long 类型防止溢出
            long num = (long) mid * (1 + mid) / 2;

            // 如果 n 小于当前总数,则说明完整行数过多,缩小右边界
            if (n < num) {
                right = mid - 1; // 修正为 right
            } else {
                // 否则,说明当前行数可以放下 n,增加左边界
                left = mid + 1;
            }
        }

        // 返回右边界,即最大完整行数
        return right; // 返回完整行数
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

神马都会亿点点的毛毛张

你的鼓励将是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值