LC1552.两球之间的磁力

原题链接:https://leetcode.cn/problems/magnetic-force-between-two-balls/

在代号为 C-137 的地球上,Rick 发现如果他将两个球放在他新发明的篮子里,它们之间会形成特殊形式的磁力。Rick 有 LC1552.两球之间的磁力 - 图1 个空的篮子,第 LC1552.两球之间的磁力 - 图2 个篮子的位置在 LC1552.两球之间的磁力 - 图3 ,Morty 想把 LC1552.两球之间的磁力 - 图4 个球放到这些篮子里,使得任意两球间 最小磁力 最大。 已知两个球如果分别位于 LC1552.两球之间的磁力 - 图5LC1552.两球之间的磁力 - 图6 ,那么它们之间的磁力为 LC1552.两球之间的磁力 - 图7 。 给你一个整数数组 LC1552.两球之间的磁力 - 图8 和一个整数 LC1552.两球之间的磁力 - 图9 ,请你返回最大化的最小磁力。

  • 示例 1:

LC1552.两球之间的磁力 - 图10

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

示例 2:

  1. 输入:position = [5,4,3,2,1,1000000000], m = 2
  2. 输出:999999999
  3. 解释:我们使用位于 1 1000000000 的篮子时最小磁力最大。
  • 提示:
  • LC1552.两球之间的磁力 - 图11
  • LC1552.两球之间的磁力 - 图12
  • LC1552.两球之间的磁力 - 图13
  • 所有 LC1552.两球之间的磁力 - 图14 中的整数 互不相同
  • LC1552.两球之间的磁力 - 图15

    思路:用二分查找代替暴力遍历

  • 希望球的最短间距的最大值尽量大一点

  • 假如只有两个球,此时的“最短间距”一定是最大的。
  • 如果加入更多的球,那么此时的“最短间距最大值”就会慢慢降低。
  • 那么,对于“最短间距的最大值”这个区间来讲,越是小就越能符合条件,所以,相当于取左边数组的右端点。
  • 假如现在已经知道了球的间距dis,如果算出怎么才能放入最多数量的球呢? 结合了贪心算法的想法:
  • pre_pos记录上一个符合条件的球的位置,初始化为position[0],计数器cnt统计放球的数量,初始化为1,遍历筐子的分布位置数组position,如果满足position[i] - pre_pos >= dis,那么执行两步操作:1.更新pre_pos为当前的position[i],2.计数器cnt += 1

    代码:

    1. class Solution {
    2. public:
    3. bool check(int dis, vector<int>& position, int m) {
    4. int all_num = 1;
    5. int pre_pos = position[0];
    6. for (int pos : position) {
    7. if (pos - pre_pos >= dis) {
    8. all_num += 1;
    9. pre_pos = pos;
    10. }
    11. }
    12. // cout << all_num << endl;
    13. return all_num >= m;
    14. }
    15. int maxDistance(vector<int>& position, int m) {
    16. // 按照某种最优的方法,最小距离越大,球的数量就越少
    17. // 逐步升高最小距离,直到球的数量恰好是m个
    18. // 相当于取左区间的右端点
    19. sort(position.begin(), position.end());
    20. int left = 1, right = 1e9 + 5;
    21. while (left < right) {
    22. int mid = (left + right + 1) / 2;
    23. if (check(mid, position, m)) {
    24. left = mid;
    25. } else {
    26. right = mid - 1;
    27. }
    28. }
    29. // check(3, position, 3);
    30. return left;
    31. }
    32. };