問題
要將傳送帶上的物品在D天內送到目的地。給定一個整形數組weights,每一個元素weights[i]表示第i個物品的重量。現在要求得能在D天內運送貨物的船的最小承重。
實例:
輸入: weights = [1,2,3,4,5,6,7,8,9,10], D = 5
輸出: 15
解釋:
A ship capacity of 15 is the minimum to ship all the packages in 5 days like this:
1st day: 1, 2, 3, 4, 5
2nd day: 6, 7
3rd day: 8
4th day: 9
5th day: 10
傳送帶上的貨物必須按照順序送出。
解析
該問題可以轉換成二分查找問題——即在承重範圍內確定貨船的最小承重。首先確定承重範圍,承重範圍最小是所有貨物的最大值(小於它那就所有貨物都運不出去了),承重範圍最大爲排序後的前n個數之後,n=temp.length/D + temp.length%D。
得到區間範圍只有就可以進行二分查找,找到最適合的承重值。這裏要做一些簡單的修改。
//承重滿足要求,但是還需要繼續往左探索,找到最小的承重值
if(com==D){
//to do
}
//承重過小,往右探索
else if{
//to do
}
//承重過大,往左探索
else{
//to do
}
Java代碼
public int shipWithinDays(int[] weights, int D) {
int temp[] = Arrays.copyOfRange(weights, 0, weights.length);
Arrays.sort(temp);
int max_one =temp[temp.length-1];
int n = temp.length/D + temp.length%D;
int max_pair = 0;
for(int i=temp.length-1;i>=temp.length-n;i--){
max_pair +=temp[i];
}
//然後將問題轉化成二分查找問題
while(max_one<=max_pair){
int mid = (max_one + max_pair)/2;
int com = judge(weights, mid);
if(com==D){
if(judge(weights, mid-1)>D) return mid;
else max_pair = mid-1;
}
else if(com>D){
max_one = mid + 1;
}
else if(com<D){
max_pair = mid -1;
}
}
return max_one;
}
//用於判斷當前位置時候能裝入
public int judge(int[] weights, int mid){
int count=0;
int ans =0;
for(int i=0;i<weights.length;i++){
ans +=weights[i];
if(ans>mid){
ans = weights[i];
count++;
}
else if(ans==mid){
ans =0;
count++;
}
if(i==weights.length-1&&ans!=0) {
count++;
}
}
return count;
}
該算法的時間複雜度爲O(nlgn),空間複雜度爲O(n);