Explorer
Data Structures & Algorithms

Count pairs (i, j) such that i < j and arr[i] > arr[j] using merge sort.

Problem Statement

Given an array of integers `arr`, return the number of inversions. Two elements `arr[i]` and `arr[j]` form an inversion if `arr[i] > arr[j]` and `i < j`.

Examples

Input: arr = [2, 4, 1, 3, 5]

Output: 3

Explanation: Inversion pairs: (2, 1), (4, 1), (4, 3).

Input: arr = [2, 3, 4, 5, 6]

Output: 0

Explanation: Combining the input according to Count Inversions logic yields 0.

Input: arr = [5, 4, 3, 2, 1]

Output: 10

Explanation: Combining the input according to Count Inversions logic yields 10.

Complexity

Time Complexity: O(N log N)

Space Complexity: O(N)

Hints

šŸ’” Hint 1: An inversion is a pair (i, j) such that i < j and arr[i] > arr[j]. šŸ’” Hint 2: Use modified Merge Sort to count inversions during the merge step. šŸ’” Hint 3: When arr[i] > arr[j] during merge, all elements from i to mid are also greater than arr[j], adding mid - i + 1 inversions.

Editorial & Approach

Problem Overview & Intuition

A brute force checks all pairs in O(N²). During Merge Sort, when picking an element from the right subarray because arr[i] > arr[j], every remaining element in the sorted left subarray [i...mid] is also strictly greater than arr[j], contributing mid - i + 1 inversions in O(N log N).

Step-by-Step Approach

  1. Divide the array into two halves recursively.
  2. Count inversions in left half and right half.
  3. During the merge step, whenever arr[i] > arr[j], add mid - i + 1 to inversion count.
  4. Return total inversions accumulated.

Optimal Implementation (JavaScript)

function countInversions(arr) {
  const temp = new Array(arr.length);
  function mergeSort(left, right) {
    let inv = 0;
    if (left < right) {
      const mid = Math.floor((left + right) / 2);
      inv += mergeSort(left, mid);
      inv += mergeSort(mid + 1, right);
      inv += merge(left, mid, right);
    }
    return inv;
  }
  function merge(left, mid, right) {
    let i = left, j = mid + 1, k = left, inv = 0;
    while (i <= mid && j <= right) {
      if (arr[i] <= arr[j]) temp[k++] = arr[i++];
      else {
        temp[k++] = arr[j++];
        inv += (mid - i + 1);
      }
    }
    while (i <= mid) temp[k++] = arr[i++];
    while (j <= right) temp[k++] = arr[j++];
    for (let p = left; p <= right; p++) arr[p] = temp[p];
    return inv;
  }
  return mergeSort(0, arr.length - 1);
}

Complexity Analysis

Time Complexity O(N log N) — standard merge sort time.
Space Complexity O(N) — auxiliary temporary array for merging.

Edge Cases & Corner Traps Handled

  • Already sorted array: returns 0.
  • Reverse sorted array: returns N * (N - 1) / 2.
  • Array with identical elements.

Count Inversions

Hard
Given an array of integers `arr`, return the number of inversions. Two elements `arr[i]` and `arr[j]` form an inversion if `arr[i] > arr[j]` and `i < j`.
Example Scenarios
1Example 1
Input: arr = [2, 4, 1, 3, 5]
Output: 3
Explanation:

Inversion pairs: (2, 1), (4, 1), (4, 3).

2Example 2
Input: arr = [2, 3, 4, 5, 6]
Output: 0
Explanation:

Combining the input according to Count Inversions logic yields 0.

3Example 3
Input: arr = [5, 4, 3, 2, 1]
Output: 10
Explanation:

Combining the input according to Count Inversions logic yields 10.

Editor
Loading Editor...
arr =
[2, 4, 1, 3, 5]
Output:Click "Run" above to execute and verify your code here.
3