↓快轉到主要內容
  1. LeetCode/

LeetCode 2563: Count the Number of Fair Pairs

·2 分鐘· ·
LeetCode Medium Two-Pointers Sorting Binary-Search Array
Wei Yi Chung
作者
Wei Yi Chung
Working at the contributing of open source, distributed systems, and data engineering.
目錄

基本資料
#

難易度: medium 第一次嘗試:2026-01-25

  • 提交紀錄:WA → TLE → WA → TLE → AC

解題思路
#

配對 (i, j) 跟順序無關(只看兩個數的和),所以可以先排序。

直接數「和落在 [lower, upper]」時,一個上界、一個下界,兩個條件的指針移動方向會打架。拆成兩個單邊條件:

count(lower <= sum <= upper) = count(sum <= upper) - count(sum <= lower - 1)

count(sum <= limit) 用對撞指針:

  • nums[left] + nums[right] > limit:right 太大,往左。
  • 否則 left 跟 left + 1..right 每一個配都成立,加上 right - left,left 往右。

我的嘗試
#

版本問題
第一版 WA對每個 i 用同一組 left、right 找另一個數的範圍,但沒限制 j > i,會配到自己、也會兩個方向都算。例如 [1, 1]、lower = upper = 2:答案是 1,這版回傳 4
第二、四版 TLE每個 i 都把指針重設成 i + 1、n - 1 再往內走,O(n^2)
第三版 WA改成 left = max(i + 1, left),讓 left 只往右,但 nums[i] 變大時,下界對應的位置其實要往左移,left 不能只往右。例如 [-2, -1, -1, -1]、lower = upper = -2:三個 -1 兩兩配對都是 -2,答案是 3,這版回傳 2

這幾版的問題都是同時處理上下界。拆成兩個單邊計數就 AC 了。

正確解法
#

class Solution:
    def countFairPairs(self, nums: List[int], lower: int, upper: int) -> int:
        nums.sort()

        def count_at_most(limit: int) -> int:     # 和 <= limit 的配對數
            left, right = 0, len(nums) - 1
            count = 0
            while left < right:
                if nums[left] + nums[right] > limit:
                    right -= 1
                else:
                    count += right - left
                    left += 1
            return count

        return count_at_most(upper) - count_at_most(lower - 1)

也可以對每個 i 在 i + 1..n - 1 用 bisect 找上下界,一樣是 O(n log n)。

複雜度
#

時間 O(n log n),空間 O(1)(不算排序)。

要特別避免的錯誤
#

  • 沒限制 j > i:配到自己或重複計算。
  • 同時用兩個指針處理上下界:下界的位置不是單調往右。
  • 每個 i 重設指針:O(n^2)。

面試口說整理
#

配對只看和,所以先排序。範圍條件拆成「和 <= upper」減掉「和 <= lower - 1」。單邊的計數用對撞指針:兩端和太大就把右端往左,否則左端跟中間每一個都能配,加上 right - left 再把左端往右。兩次都是 O(n),總時間由排序決定,O(n log n)。

相關文章

LeetCode 1498: Number of Subsequences That Satisfy the Given Sum Condition
·2 分鐘
LeetCode Medium Two-Pointers Sorting Binary-Search Array
LeetCode 1498 解題筆記:子序列只看最小值和最大值,排序後順序無關;固定最小值 nums[left],中間的元素任意選,共 2^(right - left) 種
LeetCode 825: Friends Of Appropriate Ages
·2 分鐘
LeetCode Medium Two-Pointers Sorting Binary-Search Array
LeetCode 825 解題筆記:排序後,每個人能送出邀請的對象是年齡落在 (0.5 × age + 7, age] 的一段區間,用兩個同向指針維護區間再扣掉自己
LeetCode 1471: The k Strongest Values in an Array
·1 分鐘
LeetCode Medium Two-Pointers Sorting Array
LeetCode 1471 解題筆記:排序後離中位數最遠的一定在兩端,對撞指針每次從兩端挑比較強的那個,挑 k 次
LeetCode 923: 3Sum With Multiplicity
·3 分鐘
LeetCode Medium Two-Pointers Sorting Hash-Table Counting Array
LeetCode 923 解題筆記:排序後固定第一個數、對撞指針找另外兩個;兩端值相同時用組合數一次算完,不同時把兩端各自的重複數相乘
LeetCode 948: Bag of Tokens
·1 分鐘
LeetCode Medium Two-Pointers Greedy Sorting Array
LeetCode 948 解題筆記:排序後,用最小的 token 換分數、用最大的 token 換能量;只有分數 > 0 才能換能量,換不了就停
LeetCode 3413: Maximum Coins From K Consecutive Bags
·2 分鐘
LeetCode Medium Sliding-Window Greedy Sorting Prefix-Sum Binary-Search Array
LeetCode 3413 解題筆記:最佳的 k 個袋子,一定有一端對齊某段的端點;分別算「左端對齊段的起點」和「右端對齊段的終點」(鏡像後重用同一個函式)