1. 程式人生 > >LeetCode演算法題-Arranging Coins(Java實現)

LeetCode演算法題-Arranging Coins(Java實現)

這是悅樂書的第229次更新,第241篇原創

01 看題和準備

今天介紹的是LeetCode演算法題中Easy級別的第96題(順位題號是441)。您想要以樓梯形狀形成總共n個硬幣,其中每個第k行必須具有恰好k個硬幣。給定n,找到可以形成的完整樓梯行的總數。n是一個非負整數,適合32位有符號整數的範圍。例如:
n = 5
硬幣可以形成以下行:
¤
¤¤
¤¤
因為第3行不完整,我們返回2。

n = 8
硬幣可以形成以下行:
¤
¤¤
¤¤¤
¤¤
因為第4行不完整,我們返回3。

本次解題使用的開發工具是eclipse,jdk使用的版本是1.8,環境是win7 64位系統,使用Java語言編寫和測試。

02 第一種解法

因為每一行所表示的硬幣需要和行號相等,因此我們可以直接對n從1開始做減法。使用一個變數從1開始做自加,n每次減去該變數,直到n不大於0,最後判斷n是否等於0,等於0就返回該變數,否則返回該變數減1。

public int arrangeCoins(int n) {
    int i = 0;
    while (n > 0) {
        i++;
        n -= i;
    }
    return n == 0 ? i : i-1 ;   
}


03 第二種解法

利用二分法和等差數列的特性。每行樓梯對應的硬幣數,可以構成一個公差為1的等差數列,前n行樓梯總共需要(1+n)*n/2個硬幣,我們可以使用二分法,不斷取中間值,獲取對應的硬幣數,然後和n做比較,如果等於,直接返回當前中間數,如果小於,低位變成中間位加1,如果大於,高位變成中間位減1,最後返回高位。

在計算等差數列前n個數之和時,使用long型別,以免溢位。

public int arrangeCoins2(int n) {
    int low = 0, high = n;
    while (low <= high) {
        int mid = low + (high - low)/2;
        long sum = (1L+mid)*mid/2;
        if (sum == n) {
            return mid;
        } else if (sum < n) {
            low = mid+1;
        } else {
            high = mid-1;
        }
    }
    return high;
}


04 第三種解法

還是利用等差數列的求和公式x=(1+n)×n/2,可以反向推導求n的值。

2x = (1+n)*n;

n^2 + n - 2x = 0;

此時就變成解一元二次方程的根了,2a分之負b加減根號下b的平方減4乘以a乘以c,因為n大於0,所以只用求正根即可。

n = (-1 + Math.sqrt(1-4×(-2x)))/2;

n = (-1 + Math.sqrt(1+8x))/2;

其中,我們需要注意資料型別的隱式轉換,Math.sqrt返回的double型別的資料,因此8最好是double或者long型別的。

public int arrangeCoins3(int n) {
    return (int)((-1 + Math.sqrt(1 + 8.0*n)) / 2);
}


05 小結

演算法專題目前已連續日更超過兩個月,演算法題文章96+篇,公眾號對話方塊回覆【資料結構與演算法】、【演算法】、【資料結構】中的任一關鍵詞,獲取系列文章合集。

以上就是全部內容,如果大家有什麼好的解法思路、建議或者其他問題,可以下方留言交流,點贊、留言、轉發就是對我最大的回報和支援!