当前位置: 首页 > news >正文

力扣LeetCode: 1552 两球之间的磁力

题目:

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

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

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

示例 1:

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

示例 2:

输入:position = [5,4,3,2,1,1000000000], m = 2
输出:999999999
解释:我们使用位于 1 和 1000000000 的篮子时最小磁力最大。

提示:

  • n == position.length
  • 2 <= n <= 10^5
  • 1 <= position[i] <= 10^9
  • 所有 position 中的整数 互不相同 。
  • 2 <= m <= position.length

解法:二分查找

解决思路

  1. 排序

    • 首先对 position 数组进行排序。排序后,我们可以更方便地计算任意两个篮子之间的距离。

    • 例如,position = [1, 2, 3, 4, 7],排序后仍然是 [1, 2, 3, 4, 7]

  2. 二分查找

    • 我们需要找到最大的最小磁力。最小磁力的范围是从 0 到 maxDistance,其中 maxDistance 是排序后数组中最后一个位置与第一个位置的差。

    • 例如,position = [1, 2, 3, 4, 7]maxDistance = 7 - 1 = 6

    • 使用二分查找在 [0, maxDistance] 范围内搜索最大的最小磁力。

  3. 贪心选择

    • 对于二分查找的每一个中间值 mid,我们需要检查是否可以放置 m 个球,使得任意两个球之间的磁力至少为 mid

    • 如果可以,说明 mid 是一个可能的最小磁力,我们尝试更大的值。

    • 如果不可以,说明 mid 太大,我们需要尝试更小的值。

  4. 检查函数

    • 实现一个辅助函数 canPlace,用于检查是否可以放置 m 个球,使得任意两个球之间的磁力至少为 mid

    • 通过遍历排序后的数组,贪心地放置球,确保每次放置的球与上一个放置的球的距离至少为 mid


代码实现

class Solution {
public:
    int maxDistance(vector<int>& position, int m) {
        // 1. 排序
        sort(position.begin(), position.end());
        
        // 2. 二分查找的范围
        int left = 0, right = position.back() - position[0];
        
        // 3. 二分查找
        while (left < right) {
            int mid = (left + right + 1) / 2; // 中间值
            if (canPlace(position, m, mid)) {
                left = mid; // 可以满足条件,尝试更大的值
            } else {
                right = mid - 1; // 不能满足条件,尝试更小的值
            }
        }
        
        // 4. 返回结果
        return left;
    }
    
private:
    // 检查是否可以放置 m 个球,使得任意两个球之间的磁力至少为 minDistance
    bool canPlace(const vector<int>& position, int m, int minDistance) {
        int count = 1; // 已放置的球的数量
        int last = position[0]; // 上一个放置的球的位置
        
        for (int i = 1; i < position.size(); ++i) {
            if (position[i] - last >= minDistance) {
                last = position[i]; // 放置当前球
                count++; // 已放置的球的数量加 1
                if (count >= m) {
                    return true; // 已经放置了 m 个球
                }
            }
        }
        
        return false; // 无法放置 m 个球
    }
};

举例说明

示例 1:
  • 输入:position = [1, 2, 3, 4, 7]m = 3

  • 排序后:position = [1, 2, 3, 4, 7]

  • 步骤:

    1. 二分查找范围:left = 0right = 7 - 1 = 6

    2. 第一次循环:

      • mid = (0 + 6 + 1) / 2 = 3

      • 检查是否可以放置 3 个球,磁力至少为 3:

        • 放置 1,然后放置 4(因为 4 - 1 = 3 >= 3),然后放置 7(因为 7 - 4 = 3 >= 3)。

        • 可以满足条件,更新 left = 3

    3. 第二次循环:

      • mid = (3 + 6 + 1) / 2 = 5

      • 检查是否可以放置 3 个球,磁力至少为 5:

        • 放置 1,然后无法放置其他球(因为 2 - 1 = 1 < 53 - 1 = 2 < 54 - 1 = 3 < 57 - 1 = 6 >= 5)。

        • 无法满足条件,更新 right = 4

    4. 第三次循环:

      • mid = (3 + 4 + 1) / 2 = 4

      • 检查是否可以放置 3 个球,磁力至少为 4:

        • 放置 1,然后放置 7(因为 7 - 1 = 6 >= 4),但无法放置第三个球。

        • 无法满足条件,更新 right = 3

    5. 循环结束,返回 left = 3

  • 输出:3

示例 2:
  • 输入:position = [5, 4, 3, 2, 1, 1000000000]m = 2

  • 排序后:position = [1, 2, 3, 4, 5, 1000000000]

  • 步骤:

    1. 二分查找范围:left = 0right = 1000000000 - 1 = 999999999

    2. 通过二分查找和贪心选择,最终找到最大最小磁力为 999999999

  • 输出:999999999


复杂度分析

  1. 时间复杂度

    • 排序:O(n log n),其中 n 是数组长度。

    • 二分查找:O(log(maxDistance)),其中 maxDistance 是最大位置差。

    • 检查函数:O(n),每次二分查找都需要调用一次检查函数。

    • 总时间复杂度:O(n log n + n log(maxDistance))

  2. 空间复杂度

    • 排序需要 O(log n) 的栈空间(快速排序的递归栈)。

    • 其他操作使用常数空间。

    • 总空间复杂度:O(log n)

相关文章:

  • 【java】基本数据类型和引用数据类型
  • deepseek+即梦一键生成海报
  • 上海正控ZK880 变频器基本操作
  • linux概念详解
  • 机器学习实战(1): 入门——什么是机器学习
  • SpringBoot 笔记
  • 【开源免费】基于SpringBoot+Vue.JS文理医院预约挂号系统(JAVA毕业设计)
  • 3.3 企业级AI Agent工程实践:从API设计到高可用架构的全栈开发指南
  • 1170. 比较字符串最小字母出现频次
  • 向量元素间是否相等mask矩阵
  • 《Foundation 起步》
  • Linux系统常用命令用法详解
  • 【ROS2】RViz2源码分析(七):DisplaysPanel 中的树状模型/视图
  • 网页五子棋——用户模块
  • Spring Boot 整合 Keycloak
  • 【计算机网络】TCP三次握手
  • GeekPad智慧屏编程控制(三)
  • 光谱相机在天文学领域的应用
  • 【Python爬虫(3)】解锁Python爬虫技能树:深入理解模块与包
  • cursor免费次数用完了怎么再续?以及如何更新机器码?
  • 陈刚:推动良好政治生态和美好自然生态共生共优相得益彰
  • 新任重庆市垫江县委副书记刘振已任县政府党组书记
  • 广西:坚决拥护党中央对蓝天立进行审查调查的决定
  • 上海市税务局:收到对刘某某存在涉税问题的举报,正依法依规办理
  • 《上海市建筑信息模型技术应用指南(2025版)》发布
  • 杭勇已任常州市政协党组成员,此前任常州市委常委、秘书长