↓Skip to main content
  1. LeetCode/

LeetCode 3649: Number of Perfect Pairs

·2 mins· ·
LeetCode Medium Two-Pointers Math Sorting Array
Wei Yi Chung
Author
Wei Yi Chung
Working at the contributing of open source, distributed systems, and data engineering.
Table of Contents

Meta Data
#

Difficulty: medium First Attempt: 2025-08-16

  • Submissions: Accepted (first try)

Approach
#

The key is simplifying the condition first. Let x = min(|a|, |b|) and y = max(|a|, |b|):

  • Whatever the signs, {|a - b|, |a + b|} is always {y - x, y + x}: with equal signs the subtraction cancels, with opposite signs the addition does.
  • Condition 1: min = y - x <= x, i.e. y <= 2x.
  • Condition 2: max = y + x >= y, always true.

So count pairs where the larger absolute value is <= twice the smaller one; signs and positions do not matter.

After sorting the absolute values, for each right find the leftmost left with 2 * arr[left] >= arr[right]; everything in [left, right) pairs with arr[right]. As right grows, left only moves right, so these are same-direction pointers.

My Solution
#

class Solution:
    def perfectPairs(self, nums: List[int]) -> int:
        arr = sorted(abs(x) for x in nums)
        ans = left = 0
        for right, y in enumerate(arr):
            while 2 * arr[left] < y:
                left += 1
            ans += right - left            # arr[left..right-1] all pair with y
        return ans

left stops at right at the latest (2y >= y), so it never goes out of range.

Complexity
#

Time O(n log n), space O(n).

Mistakes to Avoid
#

  • Enumerating pairs with the original condition in O(n^2): too slow for n up to 10^5.
  • Missing one of the sign cases while simplifying.

Interview Explanation
#

I simplify first: with absolute values x <= y, |a - b| and |a + b| are always y - x and y + x, so the second condition always holds and the first becomes y <= 2x. Then I sort the absolute values and, for each right end, move a left pointer that only goes right until 2 * arr[left] >= arr[right]; everything between pairs up. Time O(n log n).

Related

LeetCode 2410: Maximum Matching of Players With Trainers
·2 mins
LeetCode Medium Two-Pointers Greedy Sorting Array
LeetCode 2410 note: sort both sides, then same-direction pointers match the weakest player with the smallest trainer that is good enough
LeetCode 3627: Maximum Median Sum of Subsequences of Size 3
·2 mins
LeetCode Medium Math Greedy Sorting Game-Theory Array
LeetCode 3627 note: after sorting, each group takes the two largest and the smallest, with the second largest as the median; the answer takes every other value from the end, n / 3 of them
LeetCode 189: Rotate Array
·2 mins
LeetCode Medium Array Math Two-Pointers
LeetCode 189 note: take k %= n, then reverse three times: the whole array, the first k, and the last n - k, with O(1) extra space
LeetCode 75: Sort Colors
·2 mins
LeetCode Medium Array Two-Pointers Sorting Quicksort
LeetCode 75 note: the Dutch flag, with 0s left of low and 2s right of high; after swapping a 2 to high, do not advance, since the swapped-in value is unchecked
LeetCode 15: 3Sum
·2 mins
LeetCode Medium Array Two-Pointers Sorting
LeetCode 15 note: sort, fix the first number, and find the other two with converging pointers, skipping equal values at all three positions to avoid duplicate triplets
LeetCode 16: 3Sum Closest
·2 mins
LeetCode Medium Array Two-Pointers Sorting
LeetCode 16 note: sort, fix one number, and find the other two with converging pointers, comparing the distance abs(sum - target)