【趣味算法】1552. 两球之间的磁力——二分模板

5,371 阅读2分钟

「这是我参与2022首次更文挑战的第2天,活动详情查看:2022首次更文挑战

翻译一下题意, m个男生一起上厕所(小号), 怎样才能最大程度的避免尴尬.

——leetcode此题热评

前言

大家好,我是一条,欢迎来到我的算法频道。

只做有趣的算法题,只为面试写算法

Question

1552. 两球之间的磁力

难度:中等

Rick 有 n 个空的篮子,第 i 个篮子的位置在 position[i] ,Morty 想把 m 个球放到这些篮子里,使得任意两球间 最小磁力 最大。

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

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

示例 1:

输入:position = [1,2,3,4,7], m = 3
输出:3
解释:将 3 个球分别放入位于 147 的三个篮子,两球间的磁力分别为 [3, 3, 6]。最小磁力为 3 。我们没办法让最小磁力大于 3

Solution

热评把这道题翻译的很形象。

问题是求最小值最大,那应该怎么放球?——平均放,也就是把位置分散开。

不难想到和二分查找有关

二分模板

先补充两个二分模板。

模板1:

boolean check(int x) {}

int search(int left, int right) {
    while (left < right) {
        int mid = (left + right) >> 1;
        if (check(mid)) right = mid;
        else left = mid + 1;
    }
    return left;
}

模板2:

boolean check(int x) {}

int search(int left, int right) {
    while (left < right) {
        int mid = (left + right + 1) >> 1;
        if (check(mid)) left = mid;
        else right = mid - 1;
    }
    return left;
}

做二分题时,按照以下步骤:

  1. 写出循环条件:while (left < right),注意是 left < right,而非 left <= right
  2. 循环体内,无脑写出 mid = (left + right) >> 1
  3. 实现 check() 函数,想一下究竟要用 left = mid 还是 right = mid
  4. 如果 left = mid,那么无脑写出 else 语句 right = mid - 1,并且在 mid 计算时补充 +1,即 mid = (left + right + 1) >> 1
  5. 如果 right = mid,那么无脑写出 else 语句 left = mid,并且不需要更改 mid 的计算;
  6. 循环结束时,left 与 right 相等。

本题题解

先排序,然后二分枚举相邻两球之间的间距,只需要统计当前间距下能放下多少个小球,记为 cnt,若 cnt >= m,说明此间距符合条件。继续二分查找,最终找到符合条件的最大间距。

Code

/**
 * @author 一条coding
 */

最后

点赞,点赞,还TMD是点赞!