目录

  1. 前言
  2. 二分法基础及变种结构
  3. 小试牛刀
  4. 打怪升级
  5. 出师试炼

前言

一般来说,遇到「最值问题」通用的方法都是动态规划,而有一类「最值问题」可以用其他方法更加巧妙、简单方便的解决,这类问题的常见问法是「使……最大值尽可能小」。

这类问题也是大厂笔试面试常见题型,2020 年美团笔试题、字节面试题中都出现过。

这类问题有三大特征:

  1. 求最值(一般是最小值)
  2. 值的搜索空间是线性的
  3. 对该值有一个限制条件,并且若 x 满足条件,则 [x, +∞) 都满足条件,反之 (-∞, x] 都不满足条件。

你说的我都懂,可问题是,这是啥意思呢?叉会腰,冷静一下。

为了方便大家理解这类问题到底是个什么玩意儿,本汪在这里列出 leetcode 上的一道题目作为例子:

给定一个非负整数数组和一个整数 m,你需要将这个数组分成 m 个非空的连续子数组。设计一个算法使得这 m 个子数组各自和的最大值最小。

不熟悉二分法的同学初遇此题,看到关键词“分割成 m 份”、“最小”,就想到了动态规划。诚然此题具备了使用动态规划的一切前提条件,也确实可以通过动态规划做出来,但其时间复杂度为 O(n^2 * m) , 空间复杂度为 O(n * m).

如果你看了本汪的这篇文章,学会了用二分法解决这一类问题,那么时间复杂度可以优化到 O(n * logx), 空间复杂度可以优化到 O(1),并且思路非常简洁,代码实现也极其简单。


二分法基础及变种结构

在讲具体的方法之前,本汪先和大家一起回顾下二分法,熟悉二分法的同学可以直接跳过这部分。

最早接触二分思想的地方应该是在二分搜索中。(本质上类似快排中的 partition 思想)

二分法是在有序线性搜索空间内,利用有序性,每次搜索通过排除一半的剩余搜索空间,使 O(n) 级别的线性搜索优化到 O(logn) 级别的方法。

二叉树:我都会二分,不会还有人不会二分法吧?不会就让往西汪那小子教你

二分法的基本代码非常简单,这里就不多提了,下面用类 java 语言给出其针对「最值问题」的变种结构:

// nums 数组是搜索空间,m 是限制条件// check(x, m) 表示在搜索空间 nums 中的点 x,满足了限制条件 mpublic int binary(int[] nums, int m){     初始化 l, r 为搜索空间的起始点和终点    while(l > 1; //二分,一次搜索可以排除 mid 的左边或者右边(剩余搜索空间的一半)       if(check(mid, m)) r = mid; //因为这一类最值问题要找的是最小,mid 满足条件了,(mid, r] 就不是最小的答案了        else l = mid + 1; // mid 不满足条件,根据有序性,[l, mid] 里的数全不满足条件    }   return r;}

根据结构我们可以看出,遇到这类问题的时候只需要找到「搜索空间」、「检查条件」,然后套用结构就能轻轻松松地解决问题。

下面就让我们来用二分法解决刚刚提到的问题。


小试牛刀

题目

给定一个非负整数数组和一个整数 m,你需要将这个数组分成 m 个非空的连续子数组。设计一个算法使得这 m 个子数组各自和的最大值最小。

思路

前文提及,解决本题只需要找到「搜索空间」、「检查条件」,剩下的就是闭着眼睛套结构的事儿了。

先找「搜索空间」,因为此类问题的搜索空间都是线性的,所以找到了起始点终点,也就找到了搜索空间。

看问题描述 “子数组各自和的最大值最小”,也就是说我们搜索的点是 "子数组各自和的最大值",那么搜索空间的起始点是数组 nums 中的最大值,即 min(nums),搜索空间的终点是数组 nums 中的所有元素之和,即 sum(nums)。因此我们找到了搜索空间,为 [min(nums), sum(nums)].

再看「检查条件」。给定搜索空间 nums,和点 x,判断 x 是否满足限制条件 m。

本题的条件是“子数组各自和的最大值”,也就是说 x 和 m 个子数组各自和相比较,都要大于或者等于它们。

「搜索空间」、「检查条件」都找到了,下面闭着眼睛套结构吧~

(瑟瑟发抖.jpg) 好的,这就上代码

代码

class Solution {   // 这个方法就是直接套结构    public int splitArray(int[] nums, int m) {        long l = 0, r = 0;        for(int num: nums) {r += num; l = Math.max(l, num);} // 初始化 l 和 r        while(l > 1;         if(check(nums, mid, m)) r = mid;         else l = mid + 1;        }        return (int)r;    }        public boolean check(int[] nums, long a, int m) { // 给定搜索空间中的点 a,看它是否大于等于所有子数组的各自和     int cnt = 1;     long sum = 0;     for(int n: nums) {      sum += n;      if(sum > a) {       sum = n;       cnt ++;       if(cnt > m) return false;      }     }     return true;    }}

打怪升级

咱们再来看一道题,小伙伴们可以先自己思考,有思路的话自己动手实现下。再看看本汪给出的思路,加深理解。

题目

珂珂喜欢吃香蕉。这里有 N 堆香蕉,第 i 堆中有 piles[i] 根香蕉。警卫已经离开了,将在 H 小时后回来。

珂珂可以决定她吃香蕉的速度 K (单位:根/小时)。每个小时,她将会选择一堆香蕉,从中吃掉 K 根。如果这堆香蕉少于 K 根,她将吃掉这堆的所有香蕉,然后这一小时内不会再吃更多的香蕉。

珂珂喜欢慢慢吃,但仍然想在警卫回来前吃掉所有的香蕉。

返回她可以在 H 小时内吃掉所有香蕉的最小速度 K(K 为整数)。

往西汪:我请你们吃香蕉,可以给我点个赞吗

思路

老规矩,先找「搜索空间」,再找「检查条件」,最后闭着眼睛套结构。

「搜索空间」:H 小时内必须吃完 sum(piles) 根香蕉,所以初始点为 sum(piles) / H,一次最多只能吃一堆,所以终点为 max(piles)。因此,搜索空间为 [sum(piles) / H, max(piles)]。

「检查条件」:“在 H 小时内吃掉所有香蕉”,因此以 K 个 / 小时 的速度吃完香蕉的用时要小于等于 H。

下面就闭着眼睛套结构吧。

代码

class Solution {    public int minEatingSpeed(int[] piles, int H) {        int l = 1, r = 0; // 这里本汪为了代码的简洁性,在不影响时间复杂度的情况下,直接让初始点为 1        for(int i: piles) r = Math.max(r, i); // 一次最多吃一堆        while(l > 1;            if(check(piles, mid, H)) r = mid;            else l = mid + 1;        }        return r;    }    boolean check(int[] piles, int K, int H){        int t = 0;        for(double i: piles){            t += Math.ceil(i / K); // 一堆香蕉共计 i 个,需要 ⌈i / K⌉ 个小时吃完            if(t > H) return false; // 警卫回来了还没吃完        }        return true;    }}

出师试炼

我非常喜欢看我文章的小伙伴,个个都是人才,说话又好听,脑瓜子又聪明,还很主动的给我文章点赞。我相信砍翻两个小怪之后,你们已经是这类问题的专家了,下面就给几道题目供大伙随便玩玩。

超喜欢往西汪的文章的

关卡 1

你将会获得一系列视频片段,这些片段来自于一项持续时长为 T 秒的体育赛事。这些片段可能有所重叠,也可能长度不一。

视频片段 clips[i] 都用区间进行表示:开始于 clips[i][0]并于 clips[i][1] 结束。我们甚至可以对这些片段自由地再剪辑,例如片段 [0, 7] 可以剪切成 [0, 1] + [1, 3] + [3, 7] 三部分。

我们需要将这些片段进行再剪辑,并将剪辑后的内容拼接成覆盖整个运动过程的片段([0, T])。返回所需片段的最小数目,如果无法完成该任务,则返回 -1 。

关卡 2

牛牛有 n 件带水的衣服,干燥衣服有两种方式。

一、是用烘干机,可以每分钟烤干衣服的 k 滴水。

二、是自然烘干,每分钟衣服会自然烘干 1 滴水。

烘干机比较小,每次只能放进一件衣服。

注意,使用烘干机的时候,其他衣服仍然可以保持自然烘干状态,现在牛牛想知道最少要多少时间可以把衣服全烘干。

关卡 3

你太强了!我已经没有更多的题目给你玩了。你可以凭借这套武功闯荡江湖了!

……

……

……

等等,我说笑呢。你这小身板,要不先进我的其他训练营再练练呗?

啥,你问我的其他训练营在哪里?动动小手,点个关注,新的训练营已经在建设了,嘿嘿。

咳咳,暗示的很明显了

java 二分搜索获得大于目标数的第一位_遇到「最值问题」还在无脑动态规划?二分法考虑一下呗相关推荐

  1. java 二分搜索获得大于目标数的第一位_程序员常用查找算法(顺序、二分、插值、分块、斐波那契)...

    顺序查找 基本思想 属于线性查找和无序查找,从一端开始顺序扫描,直到找到与目标值value相等的元素. 这是最基本的查找方法,也是时间复杂度最高的查找算法. 在数据过多时,这种方法并不适用. 代码实现 ...

  2. java 二分搜索获得大于目标数的第一位_程序员数据结构算法编程,二分查找搜索算法的原理与应用介绍!...

    本文来讲一种搜索算法,即二分搜索算法,通常在面试时也会被问到. 我们先来看一个例子,在图书馆通常是根据查到的编号去找书,可以在书架上按顺序一本本地查找,也可以找到一本书不符合预期时,再跳过一大部分书再 ...

  3. java 二分搜索获得大于目标数的第一位_Java后端架构师技术图谱,你都了解多少?...

    前言 欢迎工作一到五年的Java工程师朋友们加入我们,私信回复[资料]即可获取我们提供免费的Java架构学习资料(里面有高可用.高并发.高性能及分布式.Jvm性能调优.Spring源码, MyBati ...

  4. 数显之家快讯:「SHIO世硕心语」曾国藩:人没格局,比没钱更可怕!

    数显之家快讯:「SHIO世硕心语」曾国藩:人没格局,比没钱更可怕 做人的最高意境是节制,而不是释放. 所谓大格局.高智慧,无非就是一种平静平和的内心状态. 格局越大,越不纠缠 真正有大格局的人,非常明 ...

  5. 快手(java岗)秋招三面,已拿offer「面经分享」

    地址:北京 ​ 编辑 添加图片注释,不超过 140 字(可选) 2021.9.7 一面 1. 自我介绍 2. 实习项目.背景.需求介绍 3. InnoDB优点 4. MyISAM索引底层是什么结构 5 ...

  6. 谷歌OKR工作法|目标管理法|企业团队个人效率提升「吱序APP」

    一.OKR发展史 二.什么是OKR? OKR(Objectives and Key Results)目标及关键成果法.是一套用来明确目标和跟踪目标完成情况的目标管理工具和方法. 目标(Objectiv ...

  7. sql timestep 秒数后6位_被央视批评后仍不悔改?如今带6位助理30个保镖出门!网友:气派...

    不知道大家喜不喜欢吴谨言这个女演员,去年她主演的<延禧攻略>大火,里面的角色一改往日清宫剧的傻白甜或者悲情,让人眼前一亮,也让大家一下子记住了这个怼天怼地,敢爱敢恨的小姑娘.小编也是从那会 ...

  8. ug9.0 java虚拟机安装_UG NX9.0安装方法与安装文件「详细图文教程」

    前言:UG9.0及9.0以上的版本是没有32位安装包的,如果你使用的是32位的操作系统,那么你的UG软件最高可以安装到UG8.5版本.UG9.0及其以上的版本,必须安装在64位的操作系统. PS:以后 ...

  9. 二分查找 —— 有序数组不小于(不大于)某数的第一个(最后一个)元素

    1. 不小于某数的第一个元素 def bisearch(l, e, lo, hi):while lo < hi:mi = (lo + hi)//2if e > l[mi]: lo = mi ...

最新文章

  1. spring boot学习资料以及DEMO项目
  2. mysql中transaction的实现
  3. query分页共享,可传参
  4. HBase的Shell操作
  5. Matlab dir函数
  6. Kubernetes的四种用户部署场景
  7. 大白话说Java泛型:入门、使用、原理
  8. 新手使用vue-router传参时注意事项
  9. NIOS生成Nios libaray
  10. 新年新气象[xgluxv]
  11. 机器学习笔记(二)线性回归模型实现
  12. JS开发3D建模软件
  13. 大数据分析项目生命周期
  14. X书app数美-sid分析
  15. 教matlab唱周董的《七里香》
  16. MATLAB矩阵生成
  17. 利用英超FPL数据分析球员第一期——曼联半程MVP
  18. adb命令之pm hide 与 disable
  19. 03 限制 limit
  20. 设计黄金法则永不改变

热门文章

  1. 快速入门 Nginx,这篇就够了!
  2. 也许,这样理解 HTTPS 更容易!
  3. 解决原子性问题?你首先需要的是宏观理解
  4. BAT 招聘岗位 100%都考的知识,你精通了吗?
  5. hbuilderx代码自动补全_DL时代的代码补全利器,北大出品,效果远超语言模型
  6. mxnet 查看中间层结果
  7. 检测跟踪 DeepSOCIAL:基于YOLOv4的人群距离监测 集检测、跟踪以及逆透视映射一体的系统
  8. Lite-HRNet
  9. tempfile PermissionError: [Errno 13] Permission denied
  10. Et.parse(xml) #39gbk#39 codec cant decode byte