Article Categories
- All Categories
-
Data Structure
-
Networking
-
RDBMS
-
Operating System
-
Java
-
MS Excel
-
iOS
-
HTML
-
CSS
-
Android
-
Python
-
C Programming
-
C++
-
C#
-
MongoDB
-
MySQL
-
Javascript
-
PHP
-
Economics & Finance
Python Program to Count Inversions in an array
In this article, we will learn about counting inversions in an array. An inversion occurs when a larger element appears before a smaller element in an array.
Problem statement ? We are given an array, we need to count the total number of inversions and display it.
Inversion count represents how far an array is from being sorted. For example, in array [2, 3, 8, 6, 1], the pairs (2,1), (3,1), (8,6), (8,1), and (6,1) are inversions.
What is an Inversion?
An inversion is a pair of indices (i, j) where i < j but arr[i] > arr[j]. In other words, a larger element comes before a smaller element.
Using Nested Loops (Brute Force)
The simplest approach is to check every pair of elements and count inversions ?
def count_inversions(arr):
n = len(arr)
inv_count = 0
for i in range(n):
for j in range(i + 1, n):
if arr[i] > arr[j]:
inv_count += 1
return inv_count
# Example usage
numbers = [1, 5, 3, 8, 7]
result = count_inversions(numbers)
print("Array:", numbers)
print("Total inversions:", result)
Array: [1, 5, 3, 8, 7] Total inversions: 2
Step-by-Step Execution
Let's trace through the algorithm with array [1, 5, 3, 8, 7] ?
def count_inversions_detailed(arr):
n = len(arr)
inv_count = 0
print(f"Checking array: {arr}")
for i in range(n):
for j in range(i + 1, n):
if arr[i] > arr[j]:
print(f"Inversion found: arr[{i}] = {arr[i]} > arr[{j}] = {arr[j]}")
inv_count += 1
else:
print(f"No inversion: arr[{i}] = {arr[i]} <= arr[{j}] = {arr[j]}")
return inv_count
# Detailed execution
numbers = [1, 5, 3, 8, 7]
result = count_inversions_detailed(numbers)
print(f"\nTotal inversions: {result}")
Checking array: [1, 5, 3, 8, 7] No inversion: arr[0] = 1 <= arr[1] = 5 No inversion: arr[0] = 1 <= arr[2] = 3 No inversion: arr[0] = 1 <= arr[3] = 8 No inversion: arr[0] = 1 <= arr[4] = 7 Inversion found: arr[1] = 5 > arr[2] = 3 No inversion: arr[1] = 5 <= arr[3] = 8 No inversion: arr[1] = 5 <= arr[4] = 7 No inversion: arr[2] = 3 <= arr[3] = 8 No inversion: arr[2] = 3 <= arr[4] = 7 Inversion found: arr[3] = 8 > arr[4] = 7 Total inversions: 2
Testing Different Arrays
Let's test the function with various arrays to understand the concept better ?
def count_inversions(arr):
n = len(arr)
inv_count = 0
for i in range(n):
for j in range(i + 1, n):
if arr[i] > arr[j]:
inv_count += 1
return inv_count
# Test cases
test_arrays = [
[1, 2, 3, 4, 5], # Already sorted
[5, 4, 3, 2, 1], # Reverse sorted
[2, 3, 8, 6, 1], # Random array
[1, 1, 1, 1], # All same elements
]
for arr in test_arrays:
inversions = count_inversions(arr)
print(f"Array: {arr} ? Inversions: {inversions}")
Array: [1, 2, 3, 4, 5] ? Inversions: 0 Array: [5, 4, 3, 2, 1] ? Inversions: 10 Array: [2, 3, 8, 6, 1] ? Inversions: 5 Array: [1, 1, 1, 1] ? Inversions: 0
Time and Space Complexity
| Aspect | Brute Force | Optimized (Merge Sort) |
|---|---|---|
| Time Complexity | O(n²) | O(n log n) |
| Space Complexity | O(1) | O(n) |
| Best For | Small arrays | Large arrays |
Conclusion
Inversion count measures how far an array is from being sorted. The brute force O(n²) approach works well for small arrays, while merge sort-based solutions are more efficient for larger datasets.
