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+篇,公眾號對話方塊回覆【資料結構與演算法】、【演算法】、【資料結構】中的任一關鍵詞,獲取系列文章合集。
以上就是全部內容,如果大家有什麼好的解法思路、建議或者其他問題,可以下方留言交流,點贊、留言、轉發就是對我最大的回報和支援!