Count Nice Pairs in an Array

Updated on 09 May, 2025
Count Nice Pairs in an Array header image

Problem Statement

In this problem, you are provided with an array nums containing non-negative integers. The task is to count the number of "nice" pairs (i, j) in the array where the pair satisfies two conditions:

  • The index i is less than index j (0 <= i < j < nums.length).
  • The sum of the number at the ith position and the reversed number at the jth position is equal to the sum of the number at the jth position and the reversed number at the ith position (nums[i] + rev(nums[j]) == nums[j] + rev(nums[i])).

The function rev(x) is defined as the reverse of the non-negative integer x. For instance, rev(123) would be 321 and rev(120) would be 21. Your goal is to return the count of such "nice" pairs. Given the potential size, the result should be returned modulo 109 + 7 to ensure the output is manageable.

Examples

Example 1

Input:

nums = [42,11,1,97]

Output:

2

Explanation:

The two pairs are:
- (0,3) : 42 + rev(97) = 42 + 79 = 121, 97 + rev(42) = 97 + 24 = 121.
- (1,2) : 11 + rev(1) = 11 + 1 = 12, 1 + rev(11) = 1 + 11 = 12.

Example 2

Input:

nums = [13,10,35,24,76]

Output:

4

Constraints

  • 1 <= nums.length <= 105
  • 0 <= nums[i] <= 109

Approach and Intuition

To solve this problem, we need to understand the condition under which a pair (i, j) will be considered "nice." Let's break down the condition:

  • nums[i] + rev(nums[j]) == nums[j] + rev(nums[i])

This can be re-arranged and simplified to:

  • nums[i] - rev(nums[i]) == nums[j] - rev(nums[j])

This means that for any pair (i, j) to be nice, the difference between each number and its reversal must be the same for both i and j. Thus, the approach involves following steps:

  1. Calculate diff[i] = nums[i] - rev(nums[i]) for each index i.
  2. Use a hash map to count occurrences of each unique difference.
  3. For each unique diff value, if it appears count times, the number of nice pairs contributed by this distinct difference is count * (count - 1) / 2 because any two pairs having this diff are nice pairs.
  4. Sum up all contributions to get the total number of nice pairs.
  5. Return the total count modulo 109 + 7 as per the problem’s constraints.

By decomposing and abstracting the problem using the difference values, it becomes technically feasible to compute the number of nice pairs efficiently, efficient even for large arrays, as we leverage hashing to aggregate and compute pair counts based on unique differences.

Solutions

  • C++
  • Java
  • Python
cpp
class Solution {
public:
    int countNicePairs(vector<int>& nums) {
        vector<int> diffs;
        for (int i = 0; i < nums.size(); i++) {
            diffs.push_back(nums[i] - reverseNum(nums[i]));
        }
        
        unordered_map<int, int> countMap;
        int result = 0;
        int MODULO = 1e9 + 7;
        for (int value : diffs) {
            result = (result + countMap[value]) % MODULO;
            countMap[value]++;
        }
        
        return result;
    }
    
    int reverseNum(int num) {
        int reversed = 0;
        while (num > 0) {
            reversed = reversed * 10 + num % 10;
            num /= 10;
        }
        
        return reversed;
    }
};

In this solution, you tackle the problem of counting nice pairs in an array using C++. Each nice pair in the array meets the criteria where nums[i] + rev(nums[j]) == nums[j] + rev(nums[i]) for i < j.

To solve the problem efficiently:

  • First, compute and store the difference between each element and its reverse in a new vector called diffs. This transformation simplifies the original nice pairs criteria to finding pairs with equal differences, which is equivalent to diff[i] == diff[j].

  • Utilize an unordered_map to maintain the count of each unique difference encountered. Iterate over the diffs vector to populate this map and simultaneously compute the result. If a difference value already exists in the map, increment the result by the number of times this difference has appeared before (stored in the map).

  • Since the counts can potentially grow large, you apply modular arithmetic (MODULO = 1e9 + 7) during the accumulation to ensure the result stays within bounds of typical integer limits.

  • Define an auxiliary function, reverseNum, to compute the reverse of a number efficiently. This function is repeatedly called to determine the reversed values of elements as they are processed.

The key to the solution lies in recognizing that each addition to the countMap builds a previous state for future reference, ensuring that all potential nice pairs are counted correctly as you process each number in the list. This approach ensures that your solution remains efficient and operates within O(n) complexity given that mapping operations are average constant time, O(1).

java
class Solution {
    public int countPairs(int[] input) {
        int[] tempArray = new int[input.length];
        for (int i = 0; i < input.length; i++) {
            tempArray[i] = input[i] - reverse(input[i]);
        }
        
        Map<Integer, Integer> countMap = new HashMap<>();
        int totalPairs = 0;
        int modValue = 1000000007;
        for (int value : tempArray) {
            totalPairs = (totalPairs + countMap.getOrDefault(value, 0)) % modValue;
            countMap.put(value, countMap.getOrDefault(value, 0) + 1);
        }
        
        return totalPairs;
    }
    
    public int reverse(int inputNum) {
        int revertedNumber = 0;
        while (inputNum > 0) {
            revertedNumber = revertedNumber * 10 + inputNum % 10;
            inputNum /= 10;
        }
        
        return revertedNumber;
    }
}

The provided Java solution focuses on counting "nice" pairs in an array where a pair (i, j) is defined as nice if the difference between an element and its reversed digits at i matches this condition at j. Here's a breakdown of the implemented algorithm:

  1. Define an auxiliary array to store the results of the numerical operation: each element minus its reversed value.
  2. Utilize a HashMap to keep a count of how often each result of this operation appears in the tempArray.
  3. Traverse through the tempArray to compute the total nice pairs. For each element in tempArray, add to totalPairs the number of times this element has appeared before. This keeps a running total of nice pairs.
  4. Apply a modulo operation during additions to avoid integer overflow.
  5. Define a helper method 'reverse' to compute the reversed digit of an integer.

By leveraging the auxiliary array and HashMap, the solution efficiently compiles the count of nice pairs without explicitly checking every possible pair, which significantly improves the performance. This method ensures a lower time complexity by minimizing redundant computations.

python
class Solution:
    def countPairs(self, elements: List[int]) -> int:
        def reverseNumber(number):
            inverted = 0
            while number:
                inverted = inverted * 10 + number % 10
                number //= 10
            return inverted

        values = []
        for index in range(len(elements)):
            values.append(elements[index] - reverseNumber(elements[index]))
        
        elementCount = defaultdict(int)
        pairCount = 0
        MODULO = 10 ** 9 + 7
        for value in values:
            pairCount = (pairCount + elementCount[value]) % MODULO
            elementCount[value] += 1
        
        return pairCount

The solution provided in Python is aimed at solving the problem of counting 'nice pairs' in an array. A 'nice pair' (i, j) follows the condition where i < j and elements[i] + reversed(elements[j]) = elements[j] + reversed(elements[i]). This can be simplified to check if elements[i] - reversed(elements[i]) = elements[j] - reversed(elements[j]).

  • Firstly, you define a helper function reverseNumber to reverse the digits of a given number.
  • You then create an array values to store the result of elements[i] - reversed(elements[i]) for each element in the input elements.
  • Use a dictionary elementCount to keep track of the frequency of each value in values.
  • Traverse through the values, and for each value, update your pairCount by adding the current frequency of that value from elementCount. This step ensures checking pairs without direct comparison of indices, hence optimizing the process.
  • After each update of pairCount, increment the frequency of the current value in elementCount.
  • The final answer in pairCount is obtained modulo (10^9 + 7) due to possible large numbers, ensuring it fits within typical integer limits in competitive programming environments.

This approach efficiently counts the 'nice pairs' by utilizing mathematical manipulation and hash mapping, thereby reducing the need for a direct O(n^2) comparison.

Comments

No comments yet.