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)。

代码

python 复制代码
class Solution:
    def countFairPairs(self, nums: List[int], lower: int, upper: int) -> int:
        # 对数组进行排序
        nums.sort()
        count = 0
        n = 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 + 1

        return count

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

    def find_lower_bound(self, nums, target, start, end):
        while start <= end:
            mid = (start + end) // 2
            if nums[mid] < target:
                start = mid + 1
            else:
                end = mid - 1
        return 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]。

遍历

python 复制代码
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 的元素的位置(返回该位置的前一个位置)。

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

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

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

与相向双指针方法的区别

相向双指针方法 的典型特点是:

两个指针从两端向中间移动:一个指针从数组的起始位置开始(left),另一个指针从数组的末尾位置开始(right)。

根据当前 nums[left] + nums[right] 的值来决定移动哪个指针:

如果当前和小于 lower,则 left 指针右移。

如果当前和大于 upper,则 right 指针左移。

如果当前和在 [lower, upper] 范围内,则统计符合条件的数对并调整指针。

相关推荐
Y1nhl5 分钟前
力扣_链表_python版本
开发语言·python·算法·leetcode·链表·职场和发展
qq_4017004121 分钟前
C语言中位运算以及获取低8位和高8位、高低位合并
c语言·开发语言·算法
CoovallyAIHub24 分钟前
YOLO模型优化全攻略:从“准”到“快”,全靠这些招!
深度学习·算法·计算机视觉
闻缺陷则喜何志丹29 分钟前
【BFS】 P10864 [HBCPC2024] Genshin Impact Startup Forbidden II|普及+
c++·算法·宽度优先·洛谷
MicroTech20251 小时前
微算法科技(NASDAQ: MLGO)探索Grover量子搜索算法,利用量子叠加和干涉原理,实现在无序数据库中快速定位目标信息的效果。
数据库·科技·算法
今天背单词了吗9801 小时前
算法学习笔记:8.Bellman-Ford 算法——从原理到实战,涵盖 LeetCode 与考研 408 例题
java·开发语言·后端·算法·最短路径问题
手握风云-1 小时前
优选算法的链脉之韵:链表专题
数据结构·算法·链表
Coding小公仔1 小时前
LeetCode 151. 反转字符串中的单词
开发语言·c++·算法
稳兽龙1 小时前
P1098 [NOIP 2007 提高组] 字符串的展开
c++·算法·模拟
G.E.N.2 小时前
开源!RAG竞技场(2):标准RAG算法
大数据·人工智能·深度学习·神经网络·算法·llm·rag