題目:
輸入一個長度為N的正整數陣列piles代表N堆香蕉,piles[i]代表第i堆香蕉的數量,現在要在H小時內吃完之這些香蕉,請求假設吃香蕉的速度為k,而且每小時最多吃一堆香蕉,如果吃不下的話留下到下一個小時再吃,如果吃完後這堆後,如果還有胃口,也要等待下一個小時才能吃下一堆。
求最小的k
分析:
1)一堆香蕉N,每小時吃K個,則一堆需要多久呢?
如果N%k=0,則需要N/k 小時
如果N%k!=0.則需要N/k + 1小時
2) 此問題最直接的解法是,k從1遍歷到max(piles[i]),因為再大已經沒有意義,最多一小時只能吃一堆,針對每個值計算是否可以在H小時吃完,計算第一個滿足的k,則是最小的k
/** * 有n堆食物,在H小時內吃完,每小時吃多少個食物,最小的值是多少 */ public class MinEatingSpeed { public static void main(String[] args) { int[] piles = new int[5]; int H = 5; piles[0] = 10; piles[1] = 20; piles[2] = 30; piles[3] = 40; piles[4] = 50; System.out.println(minEatingSpeed(piles,H)); } public static int minEatingSpeed(int[] piles, int H) { int max = max(piles); for (int speed = 1; speed < max; speed++) { if(canFinish(piles,speed,H)){ return speed; } } return max; } public static Boolean canFinish(int[] piles,int speed,int H){ int count = 0; for (int pile : piles) { count = count + ((pile%speed)==0?pile/speed:(pile/speed) + 1); // System.out.println("pile=" + pile + " speed=" + speed + " (pile%speed)==0?pile/speed:(pile/speed) + 1=" + (count + (pile%speed)==0?pile/speed:(pile/speed) + 1)); // count = count + (pile/speed) + ((pile%speed)>0?1:0); } return count<=H; } public static int max(int[] piles){ int max=0; for (int pile : piles) { if(pile>max){ max=pile; } } return max; } }
3)k從1開始找到max速度不夠快,可以採用二分查詢的方法,比如如果max=100,使用50,發現能在H小時內吃完,則k最小值,應該在1~50內,否則在50~100內,再次縮小到25,12,6 比直接從1遍歷要快很多
/** * 有n堆食物,在H小時內吃完,每小時吃多少個食物,最小的值是多少 */ public class MinEatingSpeed { public static void main(String[] args) { int[] piles = new int[5]; int H = 5; piles[0] = 10; piles[1] = 20; piles[2] = 30; piles[3] = 40; piles[4] = 50; //二分查詢 System.out.println(minEatingSpeed2(piles,H)); } public static int minEatingSpeed2(int[] piles, int H) { int left = 1; int right = max(piles) + 1; while (left < right) { int mid = left + (right - left) / 2; if(canFinish(piles,mid,H)){ right = mid; }else{ left = mid + 1; } } return left; } public static Boolean canFinish(int[] piles,int speed,int H){ int count = 0; for (int pile : piles) { count = count + ((pile%speed)==0?pile/speed:(pile/speed) + 1); // System.out.println("pile=" + pile + " speed=" + speed + " (pile%speed)==0?pile/speed:(pile/speed) + 1=" + (count + (pile%speed)==0?pile/speed:(pile/speed) + 1)); // count = count + (pile/speed) + ((pile%speed)>0?1:0); } return count<=H; } public static int max(int[] piles){ int max=0; for (int pile : piles) { if(pile>max){ max=pile; } } return max; } }