LeetCode C++ 441. Arranging Coins【Math/Binary Search】简单

You have a total of n coins that you want to form in a staircase shape, where every k-th row must have exactly k coins.

Given n, find the total number of full staircase rows that can be formed.

n is a non-negative integer and fits within the range of a 32-bit signed integer.

Example 1:

n = 5

The coins can form the following rows:
¤
¤ ¤
¤ ¤

Because the 3rd row is incomplete, we return 2.

Example 2:

n = 8

The coins can form the following rows:
¤
¤ ¤
¤ ¤ ¤
¤ ¤

Because the 4th row is incomplete, we return 3. 

题意:总共有 n 枚硬币,需要将它们摆成一个阶梯形状,第 k 行必须正好有 k 枚硬币。找出可形成完整阶梯行的总行数。


解法1 迭代

class Solution {
public:
    int arrangeCoins(int n) {
        if (n <= 1) return n; //n=0->0, n=1->1
        int level = 0;
        for (int i = 1; n - i >= 0; ++i) {
            ++level;
            n -= i;
        } 
        return level; 
    }
};

提交后执行效率如下:

执行用时:16 ms, 在所有 C++ 提交中击败了19.02% 的用户
内存消耗:6.1 MB, 在所有 C++ 提交中击败了20.29% 的用户

或者写成如下形式:

class Solution {
public:
    int arrangeCoins(int n) { 
        int level = 1;
        while (n >= level) {
            n -= level;
            ++level;
        }
        return level - 1;
    }
};

解法2 二分

不断二分答案,同时运用等差数列求和公式求和,和 n 比较来缩小答案范围:

class Solution {
public:
    int arrangeCoins(int n) {
        if (n <= 1) return n; //特判,注意:n=1不存在第一个满足mid*(mid+1)>2n的mid
        uint64_t lo = 0, hi = n, mid, n2 = 2ull * n; //找到最后一个满足mid*(mid+1)<=2n的mid
        while (lo < hi) { //找到第一个满足mid*(mid+1)>2n的mid
            mid = lo + (hi - lo) / 2;  
            if ((mid + 1) * mid > n2) hi = mid;
            else lo = mid + 1;
        }
        return lo - 1;
    }
};

提交后效率如下:

执行用时:4 ms, 在所有 C++ 提交中击败了81.62% 的用户
内存消耗:6.3 MB, 在所有 C++ 提交中击败了5.78% 的用户

解法3 数学

最多有 x x x 层,每层 x x x 个硬币,于是有 x ∗ ( x + 1 ) ≤ 2 ∗ n x * (x + 1) \le 2 * n x(x+1)2n ,使用一元二次方程的求根公式解出 x x x 即可: x = − b ± Δ 2 a = − b ± b 2 − 4 a c 2 a x = \frac{-b \pm \sqrt{\Delta}}{2a} = \frac{-b\pm \sqrt{b^2-4ac}}{2a} x=2ab±Δ =2ab±b24ac

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

效率最高:

执行用时:0 ms, 在所有 C++ 提交中击败了100.00% 的用户
内存消耗:6.2 MB, 在所有 C++ 提交中击败了14.59% 的用户
已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 游动-白 设计师:上身试试 返回首页