1. 程式人生 > 其它 >P13-排列硬幣-二分查詢/牛頓迭代

P13-排列硬幣-二分查詢/牛頓迭代

//排列硬幣
/*
* 總共有n枚硬幣,將他們擺成一個階梯形狀,第k行就必須正好有k枚硬幣
* 給定一個數字n,找出可形成完整階梯行的總行數。
* n是一個非負整數,並且在32位有符號整型的範圍內
*
* 假如n=5,
* ○
* ○ ○
* ○ ○   所以結果是2,只有第一第二行是完整的,第三行不完整
* */
public class P13 {
    public static void main(String[] args) {
        System.out.println(arrangeCoins(100));
        System.out.println(arrangeCoins2(
100)); System.out.println(arrangeCoins3(100)); } //1、暴力 //準備放硬幣之前,判斷行號是否小於硬幣數,是的話減行號,然後下一行 public static int arrangeCoins(int num){ //i從1開始,作為行號 for(int i=1; i<=num; i++){ num = num - i; if(num <= i){ return i; } }
return 0; } //2、二分查詢 //上面的方法需要把n放完才知道結果 /* * num個硬幣,先假設能放num行,如果num行的硬幣總數是x,x肯定大於num * 3個硬幣,假設放3行,即總數是6,6>3是必然的,答案必然在3行及以內,用二分查詢 * 10個硬幣,假設放10行,即總數是55,55必然大於10,答案必然在10行及以內,用二分查詢 * */ public static int arrangeCoins2(int num){ int low = 0; int high = num; //
假設num個硬幣放num行 while(low <= high){ int mid = (low+high) / 2; //x行硬幣總數是等差數列公式 int cost = (mid+1) * mid / 2; if(cost == num){ return mid; //找到行數 }else if(cost > num){ high = mid - 1; }else{ low = mid + 1; } } return high; } //3、牛頓迭代 public static int arrangeCoins3(int num){ if(num == 0){ return 0; } return (int)sqrt(num, num); } //公式本來是 (x + y/x) / 2,看回P8, //但因為等差數列公式是 (x+1)*x / 2 = n (n就是總數的意思,等差數列求和,即總硬幣數,x是行號) //x平方 = 2n - x,就是要求2n-x的平方根,x = 根號(2n-x) //牛頓迭代本來就是依賴一個公式 x = y/x,看回P8啊,要求的是y的平方根, //現在要求2n-x的平方根,所以要將 2n-x 代入 y private static double sqrt(double x, int num) { double res = (x + (2*num-x)/x) / 2; if(res == x){ return x; }else{ return sqrt(res, num); } } }