题意:
有两种蛋糕,第一种蛋糕有 个,第二种蛋糕有 个,要求将这些蛋糕分到 个盘子里,分法必须满足下列要求:
1. 每个盘子里只能放一种蛋糕
2. 盘子不能为空
现在让你求出满足上述要求的前提下,装有最少蛋糕数量的盘子中装的蛋糕数量最多是多少?
解法一(暴力枚举答案)
有一个显然的结论,要让能够装的盘子越多,盘子中的蛋糕数量就必须要越少。
那么,我们已经枚举了盘子中蛋糕数量的最小值了,那么显然我们让每个盘子的蛋糕数量都为这个最小值,那么可装的盘子数量一定是最多的,即 均分 蛋糕一定是最优的。
具体的,我们从大到小枚举这个最小值 ,然后我们不妨先 均分 第一种蛋糕,再 均分 第二种蛋糕,然后再判断是否可以让每个盘子都有蛋糕,即 ,如果可行直接返回 的值
代码:
class Solution { public: int splitCake(int n, int a, int b) { //max(a,b):显然最大值要让两种蛋糕都至少有一种能放完一个盘子 for(int i=max(a,b);i>=1;i--){ if(a/i+b/i>=n)return i; } return 0; } };
时间复杂度: ,我们共循环了 次,循环体内是 的,故总的时间复杂度为
空间复杂度: ,我们没有开额外的数组,没有递归调用的过程,只有有限个变量,故总的空间复杂度为
解法二(二分答案):
一个显然的结论:装有最少数量的蛋糕的盘子所装的蛋糕数量越小,所能够分的蛋糕份数(即盘子数)越大。
我们记 ,
记 ,
显然, 是在 定义域内关于 单调递减 的函数,如下图所示:
代码:
class Solution { public: int splitCake(int n, int a, int b) { int l=1,r=max(a,b);//l和r分别是二分下界和上界 int ans=0;//最后答案 while(l<r){ int mid=(l+r)>>1; if(a/mid+b/mid>=n){//如果当前mid可选,那么贪心地往mid右边继续寻找更优的答案 ans=mid; l=mid+1; }else{//如果不满足,则在mid左边寻找答案 r=mid; } } return ans; } };
时间复杂度: ,我们二分的范围大小是 ,循环体内是 的,故总的时间复杂度为
空间复杂度: ,我们没有开额外的数组,没有递归调用的过程,只有有限个变量,故总的空间复杂度为