Leetcode5438. 制作 m 束花所需的最少天数——另类的二分法

2023-11-10

引入

之前在周赛遇到5438. 制作 m 束花所需的最少天数

给你一个整数数组 bloomDay,以及两个整数 m 和 k 。
现需要制作 m 束花。制作花束时,需要使用花园中 相邻的 k 朵花 。
花园中有 n 朵花,第 i 朵花会在 bloomDay[i] 时盛开,恰好 可以用于 一束 花中。
请你返回从花园中摘 m 束花需要等待的最少的天数。如果不能摘到 m 束花则返回 -1 。
示例 1:
输入:bloomDay = [1,10,3,10,2], m = 3, k = 1
输出:3
解释:让我们一起观察这三天的花开过程,x 表示花开,而 _ 表示花还未开。
现在需要制作 3 束花,每束只需要 1 朵。
1 天后:[x, _, _, _, _] // 只能制作 1 束花
2 天后:[x, _, _, _, x] // 只能制作 2 束花
3 天后:[x, _, x, _, x] // 可以制作 3 束花,答案为 3

今天的每日一题又遇到了:410. 分割数组的最大值

这两道题看似都可以用回溯来解,实际上回溯不太好做剪枝,不做剪枝的回溯和暴力法没有什么区别。

这类求数组里的某一个值或者某一部分和的最大、最小值,往往可以用二分法
以前的二分法似乎应用场景局限在了已排序数组的查找上,这种思想是不对的。

来说下这种另类的二分法的解题步骤:

  1. 找到边界值,即二分的left和right的值。
  2. 根据left和right获取mid。
  3. 根据mid遍历数组,判断是否符合条件,并收缩left或者right的边界值。

二分法题解:制作 m 束花所需的最少天数

二分查找的步骤如下:

  1. 将花成熟的天数放进容器中,排序(排序的目的其实就是为了找到二分的left和right值)
  2. 将排序后的容器的下标作为操作对象,根据容器的值的比较结果做为依据进行二分查找。即left=0,rgiht=nums.length-1,找到中间的mid对应的天数。
  3. 依据mid对应的天数做以此遍历比较,看看当前的天数是否满足要求。注意:这个情景下的二分查找找到合适的值时不能直接返回,因为可能有更小的天数时,符合要求的总花束与当前的花束相等(总花枝不等)
import java.util.Arrays;

class Solution {
    public int minDays(int[] bloomDay, int m, int k) {
        int[] arr=new int[bloomDay.length];
        for (int i=0;i<bloomDay.length;i++){
            arr[i]=bloomDay[i];
        }
        Arrays.sort(arr);
        int left=0,right=bloomDay.length-1;
        int ans=-1;
        while (left<=right){
            int mid=(left+right)>>>1;
            int limit=arr[mid];
            if (isEligible(bloomDay,limit,k)>=m){
                //满足要求,说明mid大了
                ans=limit;
                right=mid-1;
            }else{
                left=mid+1;
            }
        }
        return ans;
    }
    public int isEligible(int[] bloomDay,int limit,int k){
        int tmp=0;
        int count=0;
        for (int i:bloomDay){
            if (i<=limit) tmp++;
            else tmp=0;
            if (tmp==k){
                count++;
                tmp=0;
            }
        }
        return count;
    }
}

二分法题解:分割数组的最大值

public class Solution {
    public int splitArray(int[] nums, int m) {
        int N = nums.length;
        if (N == 0) return 0;
        int left = nums[0], right = 0;
        //计算左边界和右边界
        for (int i : nums) {
            right += i;
            if (left < i) left = i;
        }

        //二分法查找最小值,这和养花的题一样!
        while (left < right) {
            int mid = (left + right) >>> 1;
            if (helper(mid, nums, m)) {
               right=mid;
            }else left=mid+1;
        }
        return left;
    }

    public boolean helper(int mid, int[] nums, int m) {
        int count = 1;
        int sum = 0;
        for (int i = 0; i < nums.length; i++) {
            sum += nums[i];
            if (sum > mid) {
                count++;
                sum = nums[i];
            }
        }
        return count <= m;
    }
}

二分法题解:两球之间的磁力

题目:5489.两球之间的磁力,不做赘述。

这道题我一开始使用的是dp,但是使用dp会需要三层循环,时间复杂度超了。

import java.util.*;

public class Solution {
    public int maxDistance(int[] position, int m) {
        Arrays.sort(position);
        int n=position.length;
        //dp[j][k],表示第k个新的球放置在j的位置上时的最大最小磁力。
        int[][] dp=new int[n][m+1];

        //初始值
        for (int j=0;j<n;j++){
            dp[j][1]=Integer.MAX_VALUE;
        }

        for (int i=1;i<=m;i++){            //i个球
            for (int j=0;j<n;j++){
                for (int k=1;k+j<n;k++){
                    dp[j+k][i]=Math.max(dp[j+k][i],Math.min(dp[j][i-1],position[j+k]-position[j]));
                }
            }
        }
        return dp[n-1][m];
    }
}

这道题的最佳解法是使用二分法来做题解,也就是求出一个间距mid,然后判断如果使用这个mid,是否能够塞下m个球。

import java.util.*;

public class Solution {
    public int maxDistance(int[] position, int m) {
        Arrays.sort(position);
        //low和high表示每个球的间隔的最小值和最大值
        int low = 1;
        int high = (position[position.length - 1] - position[0]) / (m - 1);
        //二分法
        int ans = 0;
        while (low <= high) {
            int mid = (low + high) >>> 1;
            if (isFit(position, m, mid)) {
                ans = mid;
                low = mid + 1;
            } else {
                //说明间隔太大,不足以放下这么多球
                high = mid - 1;
            }
        }
        return ans;
    }

    /**
     * 判断以disntance为距离能否塞下m个球
     *
     * @param position 能够放球的桶的位置
     * @param m        球的个数
     * @param distance 每个球的最小间距
     * @return
     */
    public boolean isFit(int[] position, int m, int distance) {
        int begin = position[0];
        m--;//第一个球放begin的位置
        for (int i = 0; i < position.length; i++) {
            if (position[i] - begin >= distance) {
                m--;
                begin = position[i];
            }
        }
        return m <= 0;
    }
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Leetcode5438. 制作 m 束花所需的最少天数——另类的二分法 的相关文章

  • 从0写bootloader — 最简单的bootloader和App

    地址空间划分 对于空间划分是人为定义的 bootloader编写 启动文件start s PRESERVE8 instruct is aligned by 8 bytes 指令集8字节对齐 THUMB use Thumb instructi
  • CISCN2022全国初赛题解WriteUp-MapleLeaves

    MapleLeaves WriteUp 队员 Do1phln b477ery sfc9982 0HB Web Ezpop thinkphp 6 0 12lts 存在反序列化漏洞 https www freebuf com vuls 3215
  • Unity销毁对象的问题

    最近踩了一点坑 对象有时立即销毁比较好 不然有奇怪的错误发生 比如新旧同名骨骼替换 之前的最好parent null 然后Destroy obj 如果只写Destroy的话 由于Destroy是延迟销毁对象 那么新骨骼Instantiate

随机推荐

  • stm32 IO输出举例

    以控制有源蜂鸣器为例 有源蜂鸣器是自带震动源的器件 无源蜂鸣器则需要方波来模拟震动源 1 硬件连接 我们可以看到蜂鸣器接在PB8 而且不是直接使用IO驱动蜂鸣器 蜂鸣器功率比较大 一般都会使用三极管作为输出控制 我们可以看到黄色部分说明了P
  • zookeeper配置

    基本事件单元 以毫秒为单位 必须 tickTime 2000 监听客户端连接的端口 必须 clientPort 2181 存储快照的目录 必须 dataDir F server0 zookeeper 3 4 6 dataTmp log目录
  • C语言—总结2—数组,字符数组与字符串的关系,字符串操作函数,输入输出函数

    一 数组 1 一维数组的创建 数组是一组同类型元素的集合 类型符 数组名 常量表达式 lt 1 gt 一般方法 lt 2 gt 宏定义 数组创建时 内必须是一个常量 2 数组的初始化 数组的初始化是指在创建数组的同时 给数组一些对应的初始化
  • 嵌入式Linux系统上的GCC编译器——编译过程.c .i .s .o

    开发板上没有GCC编译器需要安装 sudo apt install gcc 查看gcc版本 gcc v 下图内为gcc版本 基本语法 o 指定生成的可执行文件的名字 o 后面直接跟输出的名字就可以 E 只进行预处理 S 只编译 c 编译并汇
  • JDK8新特性-Stream流

    一 介绍 Java 8 API添加了一个新的抽象称为流Stream 可以让你以一种声明的方式处理数据 Stream 主要用于集合操作 极大的简化了代码 同时支持链式编程 Stream API可以极大提高Java程序员的生产力 让程序员写出高
  • 基于混沌搜索策略的鲸鱼优化算法-附代码

    基于混沌搜索策略的鲸鱼优化算法 文章目录 基于混沌搜索策略的鲸鱼优化算法 1 鲸鱼优化算法 2 改进鲸鱼优化算法 2 1 混沌反向学习初始化策略 2 2 收敛因子和惯性权重混沌扰动协同更新策略 2 3最优个体混沌搜索策略 3 实验结果 4
  • ajax传php变量,使用Ajax将Javascript变量传递给PHP

    目前 我正在使用Ajax来开发现有脚本 这是我以前从未使用过的东西 我在javascript文件中设置了一个变量 该变量从页面上的输入字段获取其值 我只需要使用Ajax将其发布到我的PHP页面 不知道从哪里开始 我不确定您需要查看什么代码
  • 基于支持向量机SVM的沪深300股票预测股票涨跌方向

    结果参考 https www bilibili com video BV1nY411z7Kk spm id from 333 999 0 0 附完整代码 数据
  • Linux中FTP配置文件详解

    Linux中FTP的配置文件是 etc vsftpd vsftpd conf 1 登录和对匿名用户的设置 anonymous enable YES 设置是否允许匿名用户登录FTP服务器 默认为YES local enable YES 是否允
  • 从五个方面参与孩子的编程教育

    很多家长在考虑是否让孩子学习编程的时候 会因为自己不懂编程 觉得无法参与孩子的学习过程 也不知道如何检验孩子的学习成果 内心的一系列不确定性 导致再三犹豫 其实 少儿编程的学习也是有阶段性的 家长最重要的责任往往不是所谓的 辅导 而是在启蒙
  • js逆向-无限debugger的原理及绕过

    前言 转载自 爬虫从入门到精通 12 js调试中的一些问题 无限debugger 调试干扰 内存爆破 转载自 js 无限debugger 的原理 以及解决办法 文章目录 前言 一级目录 二级目录 三级目录 一 调试检测 1 无法打开f12
  • 拖拽更新层级分类、更新层级id树:

    program mycs java description 拖拽编辑试题分类标签参数数据类 author wupeiguo create 2020 03 17 11 30 Data Accessors chain true ApiModel
  • CCS软件的Graph功能

    如何正确使用CCS自带绘图Graph功能 Single Time使用演示 点击菜单栏Tools gt Graph gt Single Time 如图所示 点开后出现如下的对话窗口 下面对里面的每一项参数进行一下说明 Acquisition
  • linux系统PC机安装(非虚拟机,以centos为例)

    centos介绍 CentOS CommunityEnterprise Operating System 中文意思是 社区企业操作系统 我们有很多人叫它 社区企业操作系统 不管你怎么叫它 它都是linux的一个发行版本 CentOS并不是全
  • C语言指针知识点(一):字符指针(char *)及其格式输出(%c%d%s等)

    类型是分配内存块大小的别名 即类型 int double char 的作用就是分配相对应大小的内存 并给程序员一个名字 int double char 方便操作 指针也是一种数据类型 定义时可以对其赋值 可赋任意地址值 但习惯赋值为NULL
  • Windows10下VTR.7中VPR项目的运行

    下载VTR7和Visual Studio2022 点击sln文件 打开vpr工程 项目升级 vpr为VS2010的项目 需要先对工程文件升级后再编译 取消较小类型检查 上方菜单 项目 VPR属性 C C 代码生成 编译链接 运行 命令行运行
  • Elasticsearch Java 操作之后查询数据未及时更新

    在请求里加这个参数 request setRefreshPolicy WriteRequest RefreshPolicy IMMEDIATE 例如 public boolean saveOrUpdate String indexName
  • ListView具有多种item布局——实现微信对话列 .

    这篇文章的效果也是大家常见的 各种通讯应用的对话列表都是这种方式 像微信 whatsapp 易信 米聊等 我们这篇文章也权当为回忆 形成简单的笔记 这篇文章参考了2009年Google IO中的 TurboChargeYourUI How
  • linux启动,挂栽,共享,忘记密码的解决方法

    Linux修改linux的启动方式 修改linux启动方式 文本方式或xwindow方式 vi etc inittab 找到id x initdefault 一行 x 3为文本方式 x 5为xwindow方式 重启机器即可生效 mount用
  • Leetcode5438. 制作 m 束花所需的最少天数——另类的二分法

    文章目录 引入 二分法题解 制作 m 束花所需的最少天数 二分法题解 分割数组的最大值 二分法题解 两球之间的磁力 引入 之前在周赛遇到5438 制作 m 束花所需的最少天数 给你一个整数数组 bloomDay 以及两个整数 m 和 k 现