↓Skip to main content
  1. LeetCode/

LeetCode 775: Global and Local Inversions

·3 mins· ·
LeetCode Medium Array Math
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: 2026-10-20 Source: extension of the merge sort practice ladder, practicing when not to use merge sort

Approach
#

nums is a permutation of 0 ~ n-1. A global inversion is any inversion; a local inversion is an inversion between neighbors. Return true if the two counts are equal.

Baseline: merge sort for the global count plus one scan for the local count, O(n log n).

Key observation: every local inversion is also a global inversion, so local is a subset of global:

global = local ∪ { inversions at distance >= 2 }

The counts are equal ⟺ no pair exists with j >= i + 2 and nums[i] > nums[j].

The problem changes from “count two things and compare” to “check whether one kind of pair exists”. For a fixed j, you only need to know whether the maximum of nums[0..j-2] exceeds nums[j], and that maximum can be maintained while scanning.

My First Attempt
#

local_inversions = 0
for i in range(n - 1):
    if nums[i] > nums[i + 1]:
        local_inversions += 1

mx = -1
for i in range(2, n):
    mx = max(mx, nums[i - 2])
    if nums[i - 2] > nums[i]:      # should compare mx
        return False
return True

Review
#

  • mx is computed but never used: comparing only nums[i - 2] misses elements at distance 3 or more. Counterexample [2, 0, 3, 1]: (2, 1) is an inversion at distance 3, so the answer is false, but this version returns true.
  • local_inversions is unnecessary: the whole point of this solution is not to count.
  • The n == 1 special case is unnecessary: range(2, n) is empty when n <= 2.

After writing, scan once: is every computed variable actually used?

Solution
#

class Solution:
    def isIdealPermutation(self, nums: list[int]) -> bool:
        mx = -1                          # max(nums[0..i-2])
        for i in range(2, len(nums)):
            mx = max(mx, nums[i - 2])
            if mx > nums[i]:
                return False             # found an inversion at distance >= 2
        return True

Alternative: every element is at most one step from home
#

A common version on the discussion board:

class Solution:
    def isIdealPermutation(self, nums: list[int]) -> bool:
        return all(abs(x - i) <= 1 for i, x in enumerate(nums))

A valid permutation is [0, 1, ..., n-1] with some adjacent, non-overlapping swaps applied. If any element is two or more steps from its home position, it must have jumped over some element, which creates an inversion at distance >= 2.

This solution relies on the input being a permutation and breaks for arbitrary integers. The prefix maximum solution does not.

Complexity
#

Both solutions run in O(n) time and O(1) space.

Mistakes to Avoid
#

  • Reaching for merge sort as soon as inversions appear, without checking whether the question asks “how many” or “are they equal”.
  • Maintaining a variable and then comparing against something else.

Interview Explanation
#

An adjacent inversion is always an inversion, so local is a subset of global. The counts are equal exactly when no inversion at distance at least 2 exists. I scan left to right, keep the maximum of nums[0..i-2], and return false as soon as it exceeds nums[i]. No counting is needed: O(n) time, O(1) space, and it does not depend on the input being a permutation.

Related

LeetCode 2523: Closest Prime Numbers in Range
·2 mins
LeetCode Medium Math Number-Theory Sieve Array
LeetCode 2523 note: sieve the primes in range, since only adjacent primes can be closest; or trial-divide rightward from left and stop at the first twin primes with gap 2
LeetCode 2761: Prime Pairs With Target Sum
·2 mins
LeetCode Medium Math Number-Theory Sieve Enumeration Array
LeetCode 2761 note: sieve primes below n, then try x up to n / 2; when x and n - x are both prime, they form a pair
LeetCode 3895: Count Digit Appearances
·1 min
LeetCode Medium Math Array
LeetCode 3895 note: convert each number to a string and add up how many times the digit appears
LeetCode 3828: Final Element After Subarray Deletions
·2 mins
LeetCode Medium Math Brainteaser Game-Theory Array
LeetCode 3828 note: Alice can leave only the first or last element on her first move, guaranteeing max(first, last); Bob can likewise keep only an end, and one deletion changes at most one end, so the answer is max(first, last)
LeetCode 1040: Moving Stones Until Consecutive II
·3 mins
LeetCode Medium Sliding-Window Math Sorting Array
LeetCode 1040 note: max moves = total gaps minus the edge gap the first move wastes; min moves uses a length-n window holding the most stones, with a special case of 2 when n - 1 stones are already consecutive and one is far away
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