LeetCode C++ 441. Arranging Coins【Math/Binary Search】簡單

memcpy0發表於2020-11-25

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% 的使用者

相關文章