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

LeetCode每日一题4.19

2563. 统计公平数对的数目

题目

在这里插入图片描述

问题分析

输入:一个整数数组 nums 和两个整数 lower 和 upper。
输出:返回满足条件的公平数对的数目,即对于所有 0 <= i < j < n,lower <= nums[i] + nums[j] <= upper 的数对 (i, j) 的数量。

思路

方法一:暴力解法(时间复杂度 O(n^2))
直接遍历所有可能的数对 (i, j) 并检查它们是否满足条件。
方法二:优化解法(二分查找)
排序:首先对数组 nums 进行排序。
遍历:然后对每个 nums[i],使用 二分查找 来找到满足条件的 nums[j](其中 j > i)的范围。
二分查找:分别找到满足 nums[i] + nums[j] <= upper 的最大 j(通过 find_upper_bound)和满足 nums[i] + nums[j] >= lower 的最小 j(通过 find_lower_bound)。

代码

class Solution:def countFairPairs(self, nums: List[int], lower: int, upper: int) -> int:# 对数组进行排序nums.sort()count = 0n = len(nums)for i in range(n):# 找到满足 nums[i] + nums[j] <= upper 的最大 j 的位置r = self.find_upper_bound(nums, upper - nums[i], i + 1, n - 1)# 找到满足 nums[i] + nums[j] >= lower 的最小 j 的位置l = self.find_lower_bound(nums, lower - nums[i], i + 1, n - 1)# 统计符合条件的数对数量if l <= r:count += r - l + 1return countdef find_upper_bound(self, nums, target, start, end):while start <= end:mid = (start + end) // 2if nums[mid] > target:end = mid - 1else:start = mid + 1return enddef find_lower_bound(self, nums, target, start, end):while start <= end:mid = (start + end) // 2if nums[mid] < target:start = mid + 1else:end = mid - 1return start

复杂度分析

时间复杂度:
排序:(O(n \log n))
遍历并二分查找:(O(n \log n))
因此,最终时间复杂度为:
[ O(n \log n) + O(n \log n) = O(n \log n) ]
空间复杂度:
遍历:(O(n))

学习

排序

排序是为了后续能够利用 二分查找 来高效地找到满足条件的 nums[j]。

遍历

for i in range(n):r = self.find_upper_bound(nums, upper - nums[i], i + 1, n - 1)l = self.find_lower_bound(nums, lower - nums[i], i + 1, n - 1)if l <= r:count += r - l + 1

遍历每个 nums[i]:对于每个 nums[i],我们需要找到所有 j > i 且满足 lower <= nums[i] + nums[j] <= upper 的 nums[j]。
找到 r 和 l:
r 是满足 nums[i] + nums[j] <= upper 的最大 j 的位置。
l 是满足 nums[i] + nums[j] >= lower 的最小 j 的位置。
统计数对:如果 l <= r,则 l 到 r 之间的所有 j 都是符合条件的,因此数对数量为 r - l + 1。

二分查找

find_upper_bound:找到第一个大于 target 的元素的位置(返回该位置的前一个位置)。

  def find_upper_bound(self, nums, target, start, end):while start <= end:mid = (start + end) // 2if nums[mid] > target:end = mid - 1else:start = mid + 1return end

find_lower_bound:找到第一个不小于 target 的元素的位置。

  def find_lower_bound(self, nums, target, start, end):while start <= end:mid = (start + end) // 2if nums[mid] < target:start = mid + 1else:end = mid - 1return start

与相向双指针方法的区别

相向双指针方法 的典型特点是:
两个指针从两端向中间移动:一个指针从数组的起始位置开始(left),另一个指针从数组的末尾位置开始(right)。
根据当前 nums[left] + nums[right] 的值来决定移动哪个指针:
如果当前和小于 lower,则 left 指针右移。
如果当前和大于 upper,则 right 指针左移。
如果当前和在 [lower, upper] 范围内,则统计符合条件的数对并调整指针。

相关文章:

  • YOLO11改进-Backbone-使用MobileMamba替换YOLO backbone 提高检测精度
  • Flutter 弹窗队列管理:实现一个线程安全的通用弹窗队列系统
  • 基于尚硅谷FreeRTOS视频笔记——15—系统配制文件说明与数据规范
  • 考公:数字推理
  • 【NLP 66、实践 ⑰ 基于Agent + Prompt Engineering文章阅读】
  • 你的电脑在开“外卖平台”?——作业管理全解析
  • QML Rectangle 组件
  • 卷积神经网络基础(二)
  • 嵌入式单片机通过ESP8266连接物联网实验
  • 06-libVLC的视频播放器:推流RTMP
  • HCIP --- OSPF综合实验
  • office软件中word里面的编号库和列表库功能
  • 在 Node.js 中使用原生 `http` 模块,获取请求的各个部分:**请求行、请求头、请求体、请求路径、查询字符串** 等内容
  • C# 预定义类型全解析
  • 实验扩充 LED显示4*4键位值
  • 单片机毕业设计选题物联网计算机电气电子类
  • Java使用javacv实现的多种音视频格式播放器
  • Qt编写推流程序/支持webrtc265/从此不用再转码/打开新世界的大门
  • ReSearch:基于强化学习的大语言模型推理搜索框架
  • JavaSpring 中使用 Redis
  • 国家税务总局镇江市税务局原纪检组组长朱永凯接受审查调查
  • 年近九旬的迪图瓦,指挥能量比盛年更为强劲
  • “6+2”小复式追加票!松江购彩者擒大乐透1672万头奖
  • 全球前瞻|中国印尼举行首次“2+2”部长级会议,美乌将签署矿产协议
  • 上海交大发布“AI十条”,鄂维南院士已任该校人工智能学院讲席教授
  • 人民文学奖颁出,董宇辉获传播贡献奖