【题型总结】二分答案之最大化最小化

news/2024/11/26 3:20:31/

最大化最小值

分享巧克力【LC1231】

You have one chocolate bar that consists of some chunks. Each chunk has its own sweetness given by the array sweetness.

You want to share the chocolate with your k friends so you start cutting the chocolate bar into k + 1 pieces using k cuts, each piece consists of some consecutive chunks.

Being generous, you will eat the piece with the minimum total sweetness and give the other pieces to your friends.

Find the maximum total sweetness of the piece you can get by cutting the chocolate bar optimally.

你有一大块巧克力,它由一些甜度不完全相同的小块组成。我们用数组 sweetness 来表示每一小块的甜度。

你打算和 K 名朋友一起分享这块巧克力,所以你需要将切割 K 次才能得到 K+1 块,每一块都由一些 连续 的小块组成。

为了表现出你的慷慨,你将会吃掉 总甜度最小 的一块,并将其余几块分给你的朋友们。

请找出一个最佳的切割策略,使得你所分得的巧克力 总甜度最大,并返回这个 最大总甜度

  • 思路:

    • 题意:将数组sweetness分割成连续的k+1个子数组,返回分割后的子数组中和最小的最大值。
    • 本题的单调性为:当**最小甜度【连续子数组和的最小值】**最大,最多分割的份数越小,那么可以通过二分查找法找到最终答案
    • 将题意转化为,当分割份数一定时,寻找最小甜度的最大值 y y y,那么可以通过二分查找的方法找到最终的 y y y,二分查找的下限为1,上限为原始数组的分成 k + 1 k+1 k+1份后的平均值
    • 二分查找的对象不是甜度数组,而是前缀和数组,为递增数组
  • 实现

    • 首先统计前缀和数组,快速计算连续子数组的和【也可以不计算 将累加值存储在变量中】
    • 当二分查找最小甜度 y y y时,需要判断能否将数组分割成 k + 1 k+1 k+1个子数组,如果能够分割成 k + 1 k+1 k+1个子数组,那么我们可以增大子数组和,以获得更大的最小甜度;如果不能放下m个球,那么减少子数组和
    • 如何判断能否分割成 k + 1 k+1 k+1个子数组?
      • 需要使每个子数组的和均大于等于最小甜度 y y y,那么可以从第一个元素开始分割合法的子数组使,得到最终的分割个数 c o u n t count count,若$count \ge k+1 $,那么表示可以分割
    class Solution {public int maximizeSweetness(int[] sweetness, int k) {int n = sweetness.length;int[] preSum = new int [n + 1];for (int i = 0; i < n; i++){preSum[i + 1] = preSum[i] + sweetness[i];}int l = 1, r = preSum[n] / (k + 1);int ans = 0;while (l <= r){int mid = (l + r) / 2;if (check(mid, preSum, k + 1)){ans = mid;l = mid + 1;}else{r = mid - 1;}}return ans;}public boolean check(int min, int[] preSum, int k){int count = 0;int preIndex = 0;for (int i = 1; i < preSum.length; i++){if (preSum[i] - preSum[preIndex] >= min){count++;preIndex = i;}}return count >= k;}
    }
    
    • 时间复杂度: O ( n + n l o g ( C ) ) O(n+nlog(C)) O(n+nlog(C)) n n n是数组的长度, C C C是原始数组的分成 k + 1 k+1 k+1份后的平均值。二分查找的时间复杂度是 O ( l o g C ) O(logC) O(logC),每次二分查找需要判断是否符合条件的时间复杂度为 O ( n ) O(n) O(n),因此总的时间复杂度为 O ( n + n l o g C ) O(n+nlogC) O(n+nlogC)
    • 空间复杂度: O ( n ) O(n) O(n),前缀和数组需要的空间
  • 实现:不使用累加和数组

    class Solution {public int maximizeSweetness(int[] sweetness, int k) {int n = sweetness.length;int sum = 0;for (int i = 0; i < n; i++){sum += sweetness[i];}int l = 1, r = sum / (k + 1);int ans = 0;while (l <= r){int mid = (l + r) / 2;if (check(mid, sweetness, k + 1)){ans = mid;l = mid + 1;}else{r = mid - 1;}}return ans;}public boolean check(int min, int[] sweetness, int k){int count = 0;int sum = 0;for (int i = 0; i < sweetness.length; i++){sum += sweetness[i];if (sum >= min){count++;sum = 0;}}return count >= k;}
    }
    
    • 复杂度
      • 时间复杂度: O ( n + n l o g ( n C ) ) O(n+nlog(nC)) O(n+nlog(nC)) n n n是数组的长度,C是数组篮子位置中的最大值。求出前缀和数组需要的时间复杂度为 O ( n ) O(n) O(n),二分查找的时间复杂度是 O ( l o g C ) O(logC) O(logC),每次二分查找需要判断是否符合条件的时间复杂度为 O ( n ) O(n) O(n),因此总的时间复杂度为 O ( n + n l o g C ) O(n+nlogC) O(n+nlogC)
      • 空间复杂度: O ( 1 ) O(1) O(1)

两球间的磁力【LC1552】

在代号为 C-137 的地球上,Rick 发现如果他将两个球放在他新发明的篮子里,它们之间会形成特殊形式的磁力。Rick 有 n 个空的篮子,第 i 个篮子的位置在 position[i] ,Morty 想把 m 个球放到这些篮子里,使得任意两球间 最小磁力 最大。

已知两个球如果分别位于 xy ,那么它们之间的磁力为 |x - y|

给你一个整数数组 position 和一个整数 m ,请你返回最大化的最小磁力。

  • 思路:

    • 首先,二分查找的核心就是找到具有单调性的正确查找对象(来自北枝大佬)

      • 一般来说,查找对象就是题目要求的值,这里为最小磁力【最小球间距】

      • 本题的单调性为,最小磁力越大,最多能放置的球的个数越小

      那么,可以将题意转化为,当小球个数一定时,寻找最小磁力的最大值 y y y,那么可以通过二分查找的方法找到最终的 y y y,二分查找的下限为1,上限为最后一个位置与第一个位置的距离

  • 实现

    • 二分查找要求数组是升序排列的,因此我们需要将位置数组position排序,然后二分查找最终答案

    • 当二分查找最小磁力 y y y时,需要判断能否放下 m m m个球,如果能够放下m个球,那么我们可以增大球间距,以获得更大的最小磁力;如果不能放下m个球,那么减少球间距

    • 如何判断当前的球间距可以放下多少个球?

      模拟迭代,第一个小球放在 p o s i t i o n [ 0 ] position[0] position[0],第二个小球放在大于 p o s i t i o n [ 0 ] + y position[0]+y position[0]+y p o s i t i o n [ i ] position[i] position[i]处……

    • 思考:当在某一个最小磁力 y y y时,可能会有每一个小球间距均大于 y y y的情况,那么此时二分查找的下一步会增大球间距,小球的个数会减小,最大的最小磁力会增大,最后得到最优解

    class Solution {public int maxDistance(int[] position, int m) {Arrays.sort(position);int n = position.length;int l = 1, r = position[n - 1] - position[0];int ans = 0;while (l <= r){int mid = (l + r) / 2;if (check(mid, position, m)){ans = mid;l = mid + 1;}else{r = mid - 1;}}return ans;}public boolean check (int y, int[] position, int m){int count = 1;int pre = position[0];for (int i = 1; i < position.length; i++){if (position[i] - pre >= y){count++;pre = position[i];}}return count >= m;}
    }
    
    • 复杂度
      • 时间复杂度: O ( n l o g ( n C ) ) O(nlog(nC)) O(nlog(nC)) n n n是数组的长度,C是数组篮子位置中的最大值。排序需要的时间复杂度为 O ( n l o g n ) O(nlog n) O(nlogn),二分查找的时间复杂度是 O ( l o g C ) O(logC) O(logC),每次二分查找需要判断是否符合条件的时间复杂度为 O ( n ) O(n) O(n),因此总的时间复杂度为 O ( n l o g ( n c ) ) O(nlog(nc)) O(nlog(nc))
      • 空间复杂度: O ( l o g n ) O(logn) O(logn),排序所需要的栈空间

礼盒的最大甜蜜度【LC2517】

You are given an array of positive integers price where price[i] denotes the price of the ith candy and a positive integer k.

The store sells baskets of k distinct candies. The tastiness of a candy basket is the smallest absolute difference of the prices of any two candies in the basket.

Return the maximum tastiness of a candy basket.

  • 思路:使用二分查找的方式寻找最大甜蜜度

    • 本题的单调性为:当**最小甜蜜度【数组中任意两个元素的差值的绝对值的最小值】**越大,糖果的可以选择的种类越小【选取的数组中的元素个数】,因此可以通过二分查找法找到最终答案
    • 将题意转化为:当选取的数量一定时,寻找最小甜蜜度的最大值 y y y,二分查找的下限为0,上限为数组中最大元素与最小元素的差值/(k-1)
  • 实现

    • 首先对price数组进行升序排序

    • 然后进行二分查找,当二分查找最小甜蜜度 y y y时,需要判断能否取出 k k k种糖果,如果能取出 k k k种糖果,那么我们可以增大差值,已获得更大的最小甜蜜度;如果不能取出 k k k中糖果,那么减小差值

    • 每次查找成功,记录当前的最小甜蜜度,最后一次的最小甜蜜度即为最大最小甜蜜度

    • 如何判断当前的差值能够取出多少种糖果?

      模拟迭代,第一种糖果取 p r i c e [ 0 ] price[0] price[0],第一种糖果取 p r i c e [ 0 ] + y price[0]+y price[0]+y p r i c e [ i ] price[i] price[i]处……

  • 代码

    class Solution {public int maximumTastiness(int[] price, int k) {Arrays.sort(price);int n = price.length;int l = 0, r = price[n - 1] - price[0];int ans = 0;while (l <= r){int mid = (r + l) / 2;if (check(price, mid ,k)){ans = mid;l = mid + 1;}else{r = mid - 1;}}return ans;}public boolean check(int[] price, int m, int k){int count = 1;int preIndex = 0;for (int i = 1; i < price.length; i++){if (price[i] - price[preIndex] >= m ){count++;preIndex = i;}}return count >= k;}
    }
    
    • 复杂度
      • 时间复杂度: O ( n l o g ( n C ) ) O(nlog(nC)) O(nlog(nC)) n n n是数组的长度,C是数组中的最大值与最小值的差值。排序需要的时间复杂度为 O ( n l o g n ) O(nlog n) O(nlogn),二分查找的时间复杂度是 O ( l o g C ) O(logC) O(logC),每次二分查找需要判断是否符合条件的时间复杂度为 O ( n ) O(n) O(n),因此总的时间复杂度为 O ( n l o g ( n c ) ) O(nlog(nc)) O(nlog(nc))
      • 空间复杂度: O ( l o g n ) O(logn) O(logn),排序所需要的栈空间

http://www.ppmy.cn/news/141896.html

相关文章

惠普彩色打印机不出颜色

蓝色打不出时检测办法&#xff1a; 菜单 -> 诊断 -> 禁用粉盒诊断 -> 勾选 然后&#xff0c;对调蓝色和红色墨粉。 看蓝色是否打的出。 如果打的出说明墨粉没有问题。 校准&#xff1a; 配置设备-打印质量-完全校准

打印机彩色打印设置(将彩色打印为黑色)

这天不知道谁手欠把打印机设置成了将彩色打印为黑色&#xff0c;害得我彩色打印的纸张都是黑麻麻的一片。真是艹蛋&#xff01; 要不是发现的及时&#xff0c;特么的我得打废多少纸张啊。 打印机彩色打印设置&#xff1a;如图中所示将彩色打印为黑色的前边选中的地方取消掉就行…

PhotoShop彩色图片打印机只有四中颜色操作步骤:

打印彩色图片打印机只有四中颜色操作步骤&#xff1a; 1、图片调成灰度模式&#xff1a; 2、建立色调分离模版选择4&#xff1a; 3、图片调整为CMYK模式&#xff1a; 4、调整魔棒工具&#xff1a; 5、用魔棒工具勾选第一个色调&#xff0c;建立新的图层—按住altdelete填…

HP500 0彩色宽幅打印机修复记录

HP500 彩色宽幅打印机打印完毕后&#xff0c;进入裁纸时&#xff0c;发生卡纸。打了HP客服的电话后&#xff0c;因为过了保修期&#xff0c;只给了一个售后的电话&#xff0c;让自己联系。经过联系后&#xff0c;客服在听了我叙述打印出现的故障现象&#xff0c;初步判断是裁纸…

打印机扫描计算机远程扫描仪,怎么用打印机扫描文件-彩色网络打印机扫描设置FTP版...

现在好多企业单位为了更好的呈现相应的资料&#xff0c;都配备了比较经济适用的柯美系列彩色网络一体机(打印&#xff0c;复印&#xff0c;扫描)&#xff1b;一般的打印与复印比较容易设置&#xff0c;只要装好驱动都没有太多问题&#xff0c;但是扫描就是一个比较头痛的问题了…

hp mfp m281fdw 彩色激光打印机不通电

机器型号&#xff1a;hp mfp m281fdw 彩色激光打印机 故障&#xff1a; 不通电 没反应 检测维修&#xff1a; 一台hp mfp m281fdw 彩色激光打印机不通电了&#xff0c;反复开机各种测试都不通电无任何反应&#xff0c;断电半小时后再次通电开机结果还是不行&#xff1b; …

MacOS12安装联想CM7120W打印机,实现彩色打印

前段时间买了一台联想CM7120W彩色激光一体机机。这个打印机的优点很明显&#xff1a;便宜&#xff0c;2500拿下&#xff1b;缺点是买了之后才知道的&#xff1a;不支持airprint&#xff0c;macos下没有驱动&#xff0c;linux倒是有驱动&#xff0c;结果用了几天罢工了&#xff…