🌈【LeetCode 441. 排列硬币 】- JavaScript(二分查找+数学方法)

127 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第14天,点击查看活动详情


说明:文章部分内容及图片出自网络,如有侵权请与我本人联系(主页有公众号:小攻城狮学前端)

作者:小只前端攻城狮、 主页:小只前端攻城狮的主页、 来源:掘金

GitHub:P-J27、 CSDN:PJ想做前端攻城狮

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。


【LeetCode 441. 排列硬币 】- JavaScript(二分查找+数学方法)

题目描述

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

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

示例 1:

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

示例 2:

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

经典二分搜索

思路分析:

  • 首先利用等差数列求和公式来解方程。
  • 得到所求结果的通项公式。即 (k+1)*k/2 = n,
  • 其中k为 (-1(+-)sqrt(1+8n))/2

实际实现中,通过设置一个起点a,一个终点b,不断的求a和b的中点值c; 然后不断判断c是过大还是过小,进而判断缩小范围。直到b-a=1为终止条件。

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

数学方法

思路分析:形成0行阶梯一共需要0个硬币,形成1行阶梯一共需要1个硬币,形成2行阶梯一共需要3个硬币,形成x行阶梯一共需要 1+2+...+x = (1+x)x/2个硬币。有以下几个条件:

  • 只有 n 个硬币的情况下,最大肯定不会超过 n 行,所以这里把搜索的右侧界限定为 n。
  • 形成 mid 行的阶梯一共需要 n个硬币,这里是数学公式。
  • right 在这里指向距离 target 最近的左侧元素的位置。

实现步骤:

  1. 获取当前层数所需硬币
  2. 每次循环减去该层硬币数
  3. 如果当前剩余的硬币少于该层数需要的,就把上一层的层数返回
var arrangeCoins = function(n) {
    if (n < 2){
        return n;
    }else {
        // 数学方法
        let k = 0;
        while ((k * (k + 1) / 2) < n){
            k++;
        }
        if ((n - k * (k - 1) / 2) < k) return k - 1;
        else return k;
    }  
};

感谢阅读,希望能对你有所帮助,文章若有错误或者侵权,可以在评论区留言或在我的主页添加公众号联系我。

写作不易,如果觉得不错,可以「点赞」+「评论」 谢谢支持❤