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

力扣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)


http://www.kler.cn/a/546888.html

相关文章:

  • Webpack代码分割、分割策略性能优化详解
  • rust学习一、入门之搭建简单开发环境
  • 【网络法医】恶意软件分析
  • Ubuntu20.04桥接网络和静态IP配置
  • 能用GPT解决的,就不用自己动手
  • 深入探讨复变函数:核心概念与关键应用
  • Django html模板的继承
  • 【H5自适应】高端科技类pbootcms网站模板 – 三级栏目、下载与招聘功能支持
  • kibana es 语法记录 elaticsearch
  • 稀土抑烟剂——为纺织品安全加持,保护您的每一寸触感
  • 系统巡检脚本分享:守护服务器的“健康卫士”
  • 【系统架构设计师】操作系统 - 进程管理 ② ( 进程状态 | 三态模型 | 五态模型 | 进程状态 划分依据 | PCB 程序控制块 的 组织方式 )
  • JavaScript 网页设计案例:经典与创新的完美结合
  • 【第5章:深度生成模型— 5.1 变分自编码器(VAE)与生成对抗网络(GAN)的基础理论】
  • STM32——HAL库开发笔记19(串口中断接收实验)(参考来源:b站铁头山羊)
  • 第3节:回归实战【新冠人数预测】
  • 高效开发!使用Chrome对MoonBit生成的Wasm进行性能分析!
  • AI大模型(如GPT、BERT等)可以通过自然语言处理(NLP)和机器学习技术,显著提升测试效率
  • FacePoke详细使用指南:如何利用开源AI工具优化照片人物表情
  • vue和Django快速创建项目