【二分查找】leetcode 441. 排列硬币

441. 排列硬币

题目描述

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

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

示例1:

在这里插入图片描述

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

示例2:

在这里插入图片描述

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

提示

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

方法一:二分查找

解题思路

每一层硬币的数量逐层加 1,可构成首项为 1、公差为 1 的等差数列,利用等差数列的求和公式,可以求得前 k 个完整阶梯行所需的硬币数量为 k ∗ ( k + 1 ) / 2 k * (k + 1) / 2 k(k+1)/2,因此可以利用二分查找来求得 n 个硬币最多可以构成的完整阶梯行的数量。
因为 1 < = n < = 2 31 − 1 1 <= n <= 2^{31} - 1 1<=n<=2311,所以 n 枚硬币至少可以构成 1 个完整阶梯行,至多可以构成 n 个完整阶梯行。

代码

class Solution {
public:
    int arrangeCoins(int n) {
    	// mid * (mid + 1) 会超出 int 表示范围,所以类型为 long long 
        long long l = 1, r = n, mid;
        // 找出 n 个硬币最多可以构成的完整阶梯行的数量
        while(l < r)
        {
            mid = (l + r + 1) >> 1;
            if(mid * (mid + 1) / 2 <= n)    l = mid;
            else    r = mid - 1;
        }
        return l;
    }
};

复杂度分析

  • 时间复杂度:O( l o g n logn logn)。
  • 空间复杂度:O(1)。

方法二:数学解方程

解题思路

设可以构成的完整阶梯行的数量为 x 行,则有
( x + 1 ) ∗ x 2 = n \frac{(x + 1) * x}{2} = n 2(x+1)x=n
整理得一元二次方程得,
x 2 + x − 2 n = 0 x^2 + x - 2n = 0 x2+x2n=0
因为 n >= 1,所以判别式
Δ = 8 n + 1 > 0 \Delta = 8n + 1 > 0 Δ=8n+1>0
解得
x 1 = − 1 − 8 n + 1 2 , x 2 = − 1 + 8 n + 1 2 x_1 = \frac{-1 - \sqrt{8n + 1}}{2} ,x_2 = \frac{-1 + \sqrt{8n + 1}}{2} x1=218n+1 x2=21+8n+1
因为至少能够构成 1 行完整阶梯行,所以负解舍去。
此时 ⌊ x 2 ⌋ \lfloor x_2 \rfloor x2 即为 n 枚硬币最多可以构成的完整阶梯行的数量。

代码

class Solution {
public:
    int arrangeCoins(int n) {
        return (int)((-1 + sqrt((long long)8 * n + 1)) / 2);
    }
};

复杂度分析

sqrt 函数的时空复杂度与 CPU 支持的指令集相关。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值