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

力扣题解2555

大家好,欢迎来到无限大的频道。

今日继续给大家带来力扣题解。

题目描述:

两个线段获得的最多奖品

在 X轴 上有一些奖品。给你一个整数数组 prizePositions ,它按照 非递减 顺序排列,其中 prizePositions[i] 是第 i 件奖品的位置。数轴上一个位置可能会有多件奖品。再给你一个整数 k 。

你可以同时选择两个端点为整数的线段。每个线段的长度都必须是 k 。你可以获得位置在任一线段上的所有奖品(包括线段的两个端点)。注意,两个线段可能会有相交。

比方说 k = 2 ,你可以选择线段 [1, 3] 和 [2, 4] ,你可以获得满足 1 <= prizePositions[i] <= 3 或者 2 <= prizePositions[i] <= 4 的所有奖品 i 。

请你返回在选择两个最优线段的前提下,可以获得的最多奖品数目。

解题思路:

这是一个典型的动态规划问题,通过巧妙的划分和二分查找我们可以高效地解决。

有一个非递减排列的奖品位置数组 prizePositions(第i个奖品的位置在prizePositions[i]),及一个整数 k 表示线段的长度。目标是选择两个长度为 k 的线段,以尽可能覆盖更多的奖品位置。每个线段可以覆盖其起始点到其起始点加上 k 的范围内的奖品,两个线段之间可以重叠,但理想情况下,重叠部分应该最小化,从而增强覆盖数量。

使用动态规划(DP)数组 dp 来存储到每个位置的最大奖品覆盖数,利用二分查找来加快寻找线段覆盖边界的过程。

先写一个最基础的二分查找函数

int lower_bound(int* arr, int size, int val) {    int low = 0, high = size;    while (low < high) {        int mid = (low + high) / 2;        if (arr[mid] < val) {            low = mid + 1;        } else {            high = mid;        }    }    return low;}//这个函数实现了二分查找,目的是寻找在给定的排序数组 arr 中//第一个不小于 val 的元素的索引。

随后我们进行设计用于计算所能得到的最大奖品数量的函数

int maximizeWin(int* prizePositions, int prizePositionsSize, int k) {    int* dp = (int*)calloc(prizePositionsSize + 1, sizeof(int));    int ans = 0;    for (int i = 0; i < prizePositionsSize; i++) {        // 查找小于 prizePositions[i] - k 的最右侧位置        int x = lower_bound(prizePositions, prizePositionsSize, prizePositions[i] - k);                // 更新最大奖品数量        ans = fmax(ans, i - x + 1 + dp[x]);                // 更新 dp 数组,dp[i + 1] 记录到达 i 的最佳覆盖数量        dp[i + 1] = fmax(dp[i], i - x + 1);    }        free(dp); // 释放分配的内存    return ans; // 返回最大奖品数量 }
解析步骤:
  1. 初始化:

    • dp 数组用于存储状态。

    • ans 变量用于记录全局最大奖品数量。

  2. 循环:

    • 遍历每一个位置 i,代表第二条线段的右端点。

    • 使用 lower_bound 函数查找当前奖品位置 prizePositions[i] 左侧的界限 prizePositions[i] - k 对应的 j 值。

  3. 更新最大奖品数量:

    • 通过 ans = fmax(ans, i - x + 1 + dp[x]),从当前 i 计算出第二条线段覆盖的数量 i - x + 1 加上第一条线段的贡献 dp[x]。

    • 这里,i - x + 1 表示第二条线段覆盖的奖品数量,dp[x] 则表示第一条线段在 prizePositions[j - 1] 之前的最优覆盖。

  4. 更新 dp 数组:

    • 使用 dp[i + 1] = fmax(dp[i], i - x + 1) 更新 dp 数组,确保 dp[i + 1] 是到目前为止所能覆盖的最大奖品数量。

  5. 内存释放和返回值:

    • 最后释放 dp 数组的内存,返回最终的最大奖品数量 ans。

时间复杂度​:

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

    • 外层循环遍历 prizePositionsSize 需 O(n)。

    • 在每次循环中,二分查找的时间复杂度为 O(log n)。

空间复杂度:

  • 空间复杂度: O(n)

    • 需要 dp 数组,大小为 prizePositionsSize + 1。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • STM32F1+HAL库+FreeTOTS学习10——任务相关API函数使用
  • Vue/cli不同环境下打包后js文件没有添加hash值-会导致缓存问题-解决
  • 基于C#+SQLServer 2005实现(CS界面)校园卡消费信息系统
  • Redis:发布(pub)与订阅(sub)实战
  • Python-pptx:如何在幻灯片中轻松插入与填充表格
  • 【线程同步】关于静态扫描时出现的静态字段访问线程同步实际问题小结
  • linux高级学习13
  • 后端面试经典问题汇总
  • python列表判断是否为空的三种方式
  • Linux: network: esp:收到了重复的包?
  • Python基础语法(1)下
  • Modbus-RTU之C语言实现
  • 智慧水务建设的核心内容
  • 异步编程的实现方式
  • 全国计算机二级考试C语言篇3——选择题
  • [分享]iOS开发-关于在xcode中引用文件夹右边出现问号的解决办法
  • 【Under-the-hood-ReactJS-Part0】React源码解读
  • iBatis和MyBatis在使用ResultMap对应关系时的区别
  • JavaScript 基本功--面试宝典
  • Java反射-动态类加载和重新加载
  • MySQL的数据类型
  • Python socket服务器端、客户端传送信息
  • Service Worker
  • yii2权限控制rbac之rule详细讲解
  • 服务器从安装到部署全过程(二)
  • 工作踩坑系列——https访问遇到“已阻止载入混合活动内容”
  • 工作中总结前端开发流程--vue项目
  • 构造函数(constructor)与原型链(prototype)关系
  • 解决jsp引用其他项目时出现的 cannot be resolved to a type错误
  • 每天一个设计模式之命令模式
  • 前端存储 - localStorage
  • 悄悄地说一个bug
  • 小程序开发之路(一)
  • 用mpvue开发微信小程序
  • 容器镜像
  • ​MPV,汽车产品里一个特殊品类的进化过程
  • ​马来语翻译中文去哪比较好?
  • #ubuntu# #git# repository git config --global --add safe.directory
  • #如何使用 Qt 5.6 在 Android 上启用 NFC
  • (7)svelte 教程: Props(属性)
  • (Java岗)秋招打卡!一本学历拿下美团、阿里、快手、米哈游offer
  • (MATLAB)第五章-矩阵运算
  • (Oracle)SQL优化基础(三):看懂执行计划顺序
  • (八)Flink Join 连接
  • (补)B+树一些思想
  • (接口封装)
  • (九)One-Wire总线-DS18B20
  • (免费领源码)Java#Springboot#mysql农产品销售管理系统47627-计算机毕业设计项目选题推荐
  • (三)Kafka离线安装 - ZooKeeper开机自启
  • (三维重建学习)已有位姿放入colmap和3D Gaussian Splatting训练
  • (一) 初入MySQL 【认识和部署】
  • (轉貼) UML中文FAQ (OO) (UML)
  • .mysql secret在哪_MySQL如何使用索引
  • .Net(C#)自定义WinForm控件之小结篇
  • .NET/C# 使用 SpanT 为字符串处理提升性能