Bird
Raised Fist0
DSA Rustprogramming

Count Inversions in Array in DSA Rust

Choose your learning style10 modes available
Mental Model
Count how many pairs of numbers are out of order in an array. Each pair where a bigger number comes before a smaller one is an inversion.
Analogy: Imagine a line of people waiting by height. Every time a taller person stands before a shorter one, it counts as a mix-up or inversion.
Array: [2, 4, 1, 3, 5]
Indices:  0  1  2  3  4
Inversions: pairs like (2,1), (4,1), (4,3)
Dry Run Walkthrough
Input: array: [2, 4, 1, 3, 5]
Goal: Count all pairs where a bigger number appears before a smaller number
Step 1: Split array into two halves: left=[2,4,1], right=[3,5]
left: [2,4,1]
right: [3,5]
Why: Divide to conquer smaller parts for easier counting
Step 2: Split left half into [2,4] and [1]
left-left: [2,4]
left-right: [1]
Why: Keep dividing until single elements for easy merging
Step 3: Split [2,4] into [2] and [4]
left-left-left: [2]
left-left-right: [4]
Why: Single elements are sorted by definition
Step 4: Merge [2] and [4], count inversions between them
merged left-left: [2,4], inversions=0
Why: No inversion because 2 < 4
Step 5: Merge [2,4] and [1], count inversions
merged left: [1,2,4], inversions=2 (pairs: (2,1), (4,1))
Why: 1 is smaller than 2 and 4, so two inversions
Step 6: Merge right half [3,5] (already sorted), inversions=0
right: [3,5], inversions=0
Why: 3 < 5, no inversion
Step 7: Merge left [1,2,4] and right [3,5], count cross inversions
merged full: [1,2,3,4,5], inversions=1 (pair: (4,3))
Why: 4 comes before 3 in original, so one inversion
Result:
Final sorted array: [1,2,3,4,5]
Total inversions: 3
Annotated Code
DSA Rust
fn merge_count(arr: &mut [i32]) -> usize {
    let n = arr.len();
    if n <= 1 {
        return 0;
    }
    let mid = n / 2;
    let mut inversions = 0;
    inversions += merge_count(&mut arr[..mid]);
    inversions += merge_count(&mut arr[mid..]);

    let mut merged = Vec::with_capacity(n);
    let (left, right) = arr.split_at(mid);
    let mut i = 0;
    let mut j = 0;

    while i < left.len() && j < right.len() {
        if left[i] <= right[j] {
            merged.push(left[i]);
            i += 1;
        } else {
            merged.push(right[j]);
            inversions += left.len() - i; // Count inversions here
            j += 1;
        }
    }

    // Append remaining elements
    merged.extend_from_slice(&left[i..]);
    merged.extend_from_slice(&right[j..]);

    // Copy back to original array
    arr.copy_from_slice(&merged);

    inversions
}

fn main() {
    let mut arr = vec![2, 4, 1, 3, 5];
    let count = merge_count(&mut arr);
    println!("Sorted array: {:?}", arr);
    println!("Total inversions: {}", count);
}
if n <= 1 { return 0; }
base case: single element has zero inversions
inversions += merge_count(&mut arr[..mid]);
count inversions in left half recursively
inversions += merge_count(&mut arr[mid..]);
count inversions in right half recursively
if left[i] <= right[j] { merged.push(left[i]); i += 1; } else { merged.push(right[j]); inversions += left.len() - i; j += 1; }
merge two halves and count cross inversions when right element is smaller
arr.copy_from_slice(&merged);
copy merged sorted array back to original
OutputSuccess
Sorted array: [1, 2, 3, 4, 5] Total inversions: 3
Complexity Analysis
Time: O(n log n) because the array is recursively split and merged, counting inversions during merge
Space: O(n) due to temporary arrays used during merging
vs Alternative: Naive approach is O(n^2) by checking all pairs; merge sort method is much faster for large arrays
Edge Cases
empty array
returns 0 inversions immediately
DSA Rust
if n <= 1 { return 0; }
array with one element
returns 0 inversions immediately
DSA Rust
if n <= 1 { return 0; }
array with all equal elements
returns 0 inversions because no element is greater than another
DSA Rust
if left[i] <= right[j]
When to Use This Pattern
When asked to count how many pairs are out of order in an array, use the merge sort counting pattern because it efficiently counts inversions while sorting.
Common Mistakes
Mistake: Counting inversions only within halves and forgetting cross inversions during merge
Fix: Add inversions += left.len() - i when right[j] is smaller than left[i] during merge
Summary
Counts how many pairs in an array are out of order by using a merge sort based method.
Use it when you need to find how 'unsorted' an array is efficiently.
The key insight is counting inversions during the merge step by knowing how many elements remain in the left half.

Practice

(1/5)
1. What does the term inversion mean in the context of an array?
easy
A. A pair of elements where the first is greater than the second and appears before it
B. A pair of elements where the first is smaller than the second and appears before it
C. The total number of elements in the array
D. The sum of all elements in the array

Solution

  1. Step 1: Understand the definition of inversion

    An inversion is a pair of elements where the first element is greater than the second and appears before it in the array.
  2. Step 2: Compare options with definition

    A pair of elements where the first is greater than the second and appears before it matches this definition exactly, while others describe different concepts.
  3. Final Answer:

    A pair of elements where the first is greater than the second and appears before it -> Option A
  4. Quick Check:

    Inversion = pair (i, j) with i < j and arr[i] > arr[j] [OK]
Hint: Inversion means earlier bigger number than a later one [OK]
Common Mistakes:
  • Confusing inversion with sorted order
  • Thinking inversion counts total elements
  • Mixing up greater and smaller element order
2. Which Rust code snippet correctly declares a function to count inversions in an array slice?
easy
A. fn count_inversions(arr: &[i32]) -> i32 { 0 }
B. fn count_inversions(arr: Vec i32 { 0 }
C. fn count_inversions(arr: &[i32]) -> usize { 0 }
D. fn count_inversions(arr: &mut [i32]) -> usize { 0 }

Solution

  1. Step 1: Identify correct function signature for counting inversions

    The function should take an immutable slice of integers and return the count as usize (non-negative integer).
  2. Step 2: Compare options

    fn count_inversions(arr: &[i32]) -> usize { 0 } uses &[i32] for input and usize for output, which is correct. fn count_inversions(arr: Vec i32 { 0 } takes ownership (Vec) and returns i32 (can be negative). fn count_inversions(arr: &mut [i32]) -> usize { 0 } uses mutable slice unnecessarily. fn count_inversions(arr: &[i32]) -> i32 { 0 } returns i32 which can be negative, not ideal for count.
  3. Final Answer:

    fn count_inversions(arr: &[i32]) -> usize { 0 } -> Option C
  4. Quick Check:

    Immutable slice input + usize output = correct signature [OK]
Hint: Use &[i32] input and usize output for count functions [OK]
Common Mistakes:
  • Using Vec instead of slice for input
  • Returning signed integer for count
  • Using mutable slice when not needed
3. What is the output of the following Rust code snippet counting inversions?
fn main() {
    let arr = [2, 4, 1, 3, 5];
    let mut count = 0;
    for i in 0..arr.len() {
        for j in i+1..arr.len() {
            if arr[i] > arr[j] {
                count += 1;
            }
        }
    }
    println!("{}", count);
}
medium
A. 4
B. 3
C. 2
D. 5

Solution

  1. Step 1: Identify all inversion pairs in the array

    Array: [2, 4, 1, 3, 5]. Inversions are (2,1), (4,1), (4,3). Total 3 inversions.
  2. Step 2: Confirm count from nested loops

    Loops check all pairs i < j. Each inversion increments count by 1. Final count is 3.
  3. Final Answer:

    3 -> Option B
  4. Quick Check:

    Count inversions by pairs = 3 [OK]
Hint: Count pairs where earlier number is bigger than later [OK]
Common Mistakes:
  • Counting non-inversion pairs
  • Missing some inversion pairs
  • Confusing indices order
4. The following Rust code attempts to count inversions but has a bug. What is the bug?
fn count_inversions(arr: &[i32]) -> usize {
    let mut count = 0;
    for i in 0..arr.len() {
        for j in 0..arr.len() {
            if arr[i] > arr[j] {
                count += 1;
            }
        }
    }
    count
}
medium
A. Inner loop should start from i+1, not 0
B. Count variable should be i32, not usize
C. Function should take mutable slice
D. Comparison operator should be < instead of >

Solution

  1. Step 1: Analyze loop ranges for counting inversions

    Inversion counts pairs where i < j and arr[i] > arr[j]. Inner loop starting at 0 compares all pairs including i >= j, causing double counting and invalid pairs.
  2. Step 2: Correct inner loop start index

    Inner loop should start at i+1 to ensure only pairs with i < j are counted once.
  3. Final Answer:

    Inner loop should start from i+1, not 0 -> Option A
  4. Quick Check:

    Loop indices must ensure i < j for correct inversion count [OK]
Hint: Inner loop must start after outer index to avoid double count [OK]
Common Mistakes:
  • Starting inner loop at 0 causing double counting
  • Using wrong comparison operator
  • Changing input slice to mutable unnecessarily
5. Given the array [8, 4, 2, 1], what is the number of inversions? Use the merge sort based approach to count inversions efficiently.
hard
A. 5
B. 3
C. 4
D. 6

Solution

  1. Step 1: Understand merge sort inversion counting

    Merge sort counts inversions by counting how many elements from right subarray are placed before left subarray elements during merge.
  2. Step 2: Count inversions in [8,4,2,1]

    Pairs: (8,4), (8,2), (8,1), (4,2), (4,1), (2,1) total 6 inversions.
  3. Final Answer:

    6 -> Option D
  4. Quick Check:

    All pairs where left > right count to 6 [OK]
Hint: Count pairs where left number bigger than right during merge [OK]
Common Mistakes:
  • Counting only adjacent pairs
  • Missing some inversion pairs
  • Confusing merge sort steps
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard