题意整理
- 给定n件带水的衣服,用一个数组记录每个衣服的水滴数。
- 现在要将所有衣服烘干,有两种方式,一种是自然烘干,每件衣服减少一滴水;另一种是机器烘干,其中一件衣服减少k滴水,剩下的衣服减少一滴水(自然烘干)。
- 求最少花多长时间将所有衣服烘干。
方法一(枚举)
1.解题思路
- 首先确定花费时间的左右边界,n大于等于1,说明至少有一件衣服待烘干,至少花费1分钟,左边界为1。如果所有衣服均自然烘干,花费时间最长,此时水滴最多的衣服即是总花费时间,对应右边界。
- 然后判断某个时间time内,是否能烘干所有衣服,如果a数组内衣服水滴数小于等于time,说明能自然烘干,所以只需考虑大于time的情况。如果某件衣服水滴数大于time,假设其机器烘烤时间为t,则自然烘烤时间为time-t,对应烘干的水滴数为,这个水滴数必须大于等于,对应的衣服才能在time时间内烘干,所以有,整理得:,所以每件衣服得机器烘干时间至少为t。将所有机器烘干时间累加,如果小于等于time,说明time时间是可行的。
2.代码实现
import java.util.*; public class Solution { /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * * 计算最少要多少时间可以把所有的衣服全烘干 * @param n int整型 n件衣服 * @param a int整型一维数组 n件衣服所含水量数组 * @param k int整型 烘***1分钟可以烘干的水量 * @return int整型 */ public int dryClothes (int n, int[] a, int k) { //求最大值 int max=-1; for(int i=0;i<n;i++){ max=Math.max(max,a[i]); } //花费时间在1到max之间 for(int i=1;i<=max;i++){ //看i时间内,是否能烘干所有衣服 if(check(i,a,k)){ return i; } } return -1; } //time是用于烘烤的总时间花费 private boolean check(int time,int[] a,int k){ //烘***用时 int dryTime=0; for(int i=0;i<a.length;i++){ //取大于等于(a[i]-time)/(k-1)的时间花费 if(a[i]>time){ if((a[i]-time)%(k-1)==0){ dryTime+=(a[i]-time)/(k-1); } else{ dryTime+=(a[i]-time)/(k-1)+1; } } //只要大于总时间花费,说明time时间内不能烘干所有衣服 if(dryTime>time){ return false; } } return true; } }
3.复杂度分析
- 时间复杂度:check函数的时间复杂度为,假设a数组最大值为max,最坏情况下,需执行max次check函数,所以时间复杂度为。
- 空间复杂度:需要额外常数级别的空间,所以空间复杂度为。
方法二(二分查找)
1.解题思路
- 确定左右边界以及检查time时间是否可行的思路和方法一相同。
- 然后查找的时候,可以考虑二分查找,因为从l到r是单调递增的,如果某个time可行,则大于等于time的时间也一定可行,只需确定可行域的左边界,即可找到最少的时间花费。
动图展示:
2.代码实现
import java.util.*; public class Solution { /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * * 计算最少要多少时间可以把所有的衣服全烘干 * @param n int整型 n件衣服 * @param a int整型一维数组 n件衣服所含水量数组 * @param k int整型 烘***1分钟可以烘干的水量 * @return int整型 */ public int dryClothes (int n, int[] a, int k) { //求最大值 int max=-1; for(int i=0;i<n;i++){ max=Math.max(max,a[i]); } //确定左右边界 int l=1; int r=max; //二分,取可行域的左边界 while(l<r){ int mid=l+(r-l)/2; //如果满足条件,缩小可行域 if(check(mid,a,k)){ r=mid; } //不满足,排除左边所有数值 else{ l=mid+1; } } return l; } //time是用于烘烤的总时间花费 private boolean check(int time,int[] a,int k){ //烘***用时 int dryTime=0; for(int i=0;i<a.length;i++){ //取大于等于(a[i]-time)/(k-1)的时间花费 if(a[i]>time){ if((a[i]-time)%(k-1)==0){ dryTime+=(a[i]-time)/(k-1); } else{ dryTime+=(a[i]-time)/(k-1)+1; } } //只要大于总时间花费,说明time时间内不能烘干所有衣服 if(dryTime>time){ return false; } } return true; } }
3.复杂度分析
- 时间复杂度:check函数的时间复杂度为,假设a数组最大值为max,需执行次check函数,所以时间复杂度为。
- 空间复杂度:需要额外常数级别的空间,所以空间复杂度为。