题意整理
- 给定n个盘子以及a、b两种蛋糕,蛋糕各有一定数量。
- 要求每个盘子都有蛋糕,且只有一种蛋糕。
- 求蛋糕数最少的盘子最多能分多少蛋糕。
方法一(枚举)
1.解题思路
- 由于a、b两种蛋糕的盘子数之和固定为n,只要枚举出a蛋糕的盘子数,b蛋糕盘子数也确定了。
- 然后计算最少a蛋糕数量的最大值,以及最少b蛋糕数量的最大值,取较小的,用计算出的值跟新结果,找到所有满足条件的最大的结果。
2.代码实现
import java.util.*; public class Solution { /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * * 处理函数,返回在所有分法中,蛋糕数量最少的盘子中分到最多的蛋糕数量 * @param n int整型 n个盘子 * @param a int整型 a蛋糕数量 * @param b int整型 b蛋糕数量 * @return int整型 */ public int splitCake (int n, int a, int b) { //结果变量 int res=1; //i表示装a蛋糕的盘子数 for(int i=1;i<n;i++){ //最少数量a蛋糕的最大值 int diskA=a/i; //最少数量b蛋糕的最大值 int diskB=b/(n-i); res=Math.max(res,Math.min(diskA,diskB)); } return res; } }
3.复杂度分析
- 时间复杂度:循环体总共需执行次,所以时间复杂度为。
- 空间复杂度:需要额外常数级别的空间,所以空间复杂度为。
方法二(二分查找)
1.解题思路
- 首先确定所求结果可能的最小值和最大值,每个盘子至少装一个蛋糕,所以最小值是1,只有两个盘子的时候,相应装的蛋糕数最多,此时最少的蛋糕数中最多的可能是a,也可能是b,取两者中的较小者。
- 然后进行二分查找,只要结果能分够n个盘子,则可以继续寻找更大的结果(往右边找);如果分不够,则必须减小结果的值(往左边找)。
- 由于要找可行域的右边界,取中值的时候需要上取整,防止死循环。
动图展示:
2.代码实现
import java.util.*; public class Solution { /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * * 处理函数,返回在所有分法中,蛋糕数量最少的盘子中分到最多的蛋糕数量 * @param n int整型 n个盘子 * @param a int整型 a蛋糕数量 * @param b int整型 b蛋糕数量 * @return int整型 */ public int splitCake (int n, int a, int b) { //二分的左右边界 int l=1; int r=Math.min(a,b); while(l<r){ //因为要找可行域的右边界,这里需要上取整,防止死循环 int mid=l+(r-l+1)/2; //校验mid是否可行,如果可行,则寻找更大的mid if(check(n,a,b,mid)){ l=mid; } else{ r=mid-1; } } return l; } //最少蛋糕数量是mid时,总共可分配的盘子数应大于等于n private boolean check(int n, int a, int b,int mid){ return a/mid+b/mid>=n; } }
3.复杂度分析
- 时间复杂度:二分查找时,每次缩小一半的范围,需要查找次,所以时间复杂度为。
- 空间复杂度:需要额外常数级别的空间,所以空间复杂度为。