前端算法第一四九期-排列硬币

150 阅读1分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第5天,点击查看活动详情

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

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

示例 1:

图片.png

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

示例 2:

图片.png

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

二分查找

根据等差数列求和公式可知,前 k 个完整阶梯行所需的硬币数量为

total=k×(k+1)/2total=k×(k+1)/2

因此,可以通过二分查找计算 n 枚硬币可形成的完整阶梯行的总行数。

因为 1n23111 \le n \le 2^{31} -1,所以 n 枚硬币至少可以组成 1 个完整阶梯行,至多可以组成 n 个完整阶梯行(在 n=1 时得到)。

var arrangeCoins = function(n) {
    let left = 1, right = n;
    while (left < right) {
        const mid = Math.floor((right - left + 1) / 2) + left;
        if (mid * (mid + 1) <= 2 * n) {
            left = mid;
        } else {
            right = mid - 1;
        }
    }
    return left;
};

复杂度分析

  • 时间复杂度:O(log⁡n)。
  • 空间复杂度:O(1)。

图片.png

数学

假设 nn 个硬币最多凑出 xx 行,根据等差数列求和公式 Sn=na1+n(n1)2dS_n = n * a_1 + \frac{n * (n - 1)}{2} * d(首项和公差均为 11),可得 nnxx 的关系:

x(x+1)2<=n\frac{x * (x + 1)}{2} <= n

class Solution {
    public int arrangeCoins(int n) {
        return (int)((Math.sqrt(1 + 8.0 * n) - 1) / 2);
    }
}

图片.png

遍历求和

遍历完整的阶梯,求各个阶梯的累加和,如果加上某层后,累加和大于n,则这一层不完整。

const arrangeCoins = n => {
    let sum = 0;
    for (let i = 1; i <= n; i++) {
        sum += i;
        if (sum > n) return i - 1;
    }
    // n==1的情况
    return 1;
};