持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第14天,点击查看活动详情
说明:文章部分内容及图片出自网络,如有侵权请与我本人联系(主页有公众号:小攻城狮学前端)
作者:小只前端攻城狮、 主页:小只前端攻城狮的主页、 来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
【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 最近的左侧元素的位置。
实现步骤:
- 获取当前层数所需硬币
- 每次循环减去该层硬币数
- 如果当前剩余的硬币少于该层数需要的,就把上一层的层数返回
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;
}
};
感谢阅读,希望能对你有所帮助,文章若有错误或者侵权,可以在评论区留言或在我的主页添加公众号联系我。
写作不易,如果觉得不错,可以「点赞」+「评论」 谢谢支持❤