↓快轉到主要內容
  1. LeetCode/

LeetCode 775: Global and Local Inversions

·2 分鐘· ·
LeetCode Medium Array Math
Wei Yi Chung
作者
Wei Yi Chung
Working at the contributing of open source, distributed systems, and data engineering.
目錄

基本資料
#

難易度: medium 第一次嘗試:2026-10-20 來源:Merge sort 練習梯子的延伸題,練「什麼時候不用 merge sort」

解題思路
#

nums 是 0 ~ n-1 的排列。global inversion 是一般的逆序對,local inversion 是相鄰的逆序對。兩者數量相等就回傳 true。

Baseline:用 merge sort 算 global、掃一遍算 local,O(n log n)。

關鍵觀察:local inversion 一定也是 global inversion,所以 local 是 global 的子集:

global = local ∪ { 距離 >= 2 的逆序對 }

數量相等 ⟺ 不存在 j >= i + 2 且 nums[i] > nums[j] 的 pair。

題目從「數兩個數量再比較」變成「檢查一種 pair 存不存在」。固定 j,只要知道 nums[0..j-2] 的最大值有沒有比 nums[j] 大,這個最大值可以邊掃邊維護。

我的第一版
#

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]:      # 應該比較 mx
        return False
return True

檢討
#

  • 算了 mx 卻沒用到:只比較 nums[i - 2],漏掉距離 3 以上的元素。反例 [2, 0, 3, 1]:(2, 1) 是距離 3 的逆序對,正確答案是 false,這版回傳 true。
  • local_inversions 是多餘的:這個解法的重點就是不需要計數。
  • n == 1 的特判也是多餘的:range(2, n) 在 n <= 2 時是空的。

寫完掃一遍:每個算出來的變數,後面都有被用到嗎?

正確解法
#

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             # 找到距離 >= 2 的逆序對
        return True

另一種解法:每個元素離本位最多 1 格
#

討論區常見的寫法:

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

符合條件的排列,等於從 [0, 1, ..., n-1] 出發,做幾次相鄰且互不重疊的交換。只要有元素離本位 2 格以上,它就一定「跳過」了某個元素,形成距離 >= 2 的逆序對。

這個解法依賴「是排列」的條件,換成任意整數陣列就失效。前綴最大值的解法不依賴。

複雜度
#

兩種解法都是時間 O(n)、空間 O(1)。

要特別避免的錯誤
#

  • 看到逆序對就直接用 merge sort,沒有先看題目問的是「有幾個」還是「相不相等」。
  • 維護了變數卻比較錯對象。

面試口說整理
#

相鄰的逆序對一定也是逆序對,所以 local 是 global 的子集。兩者相等,等價於不存在距離至少 2 的逆序對。我從左往右掃,維護 nums[0..i-2] 的最大值,只要它大於 nums[i] 就回傳 false。這樣不需要真的計數,時間 O(n)、空間 O(1),而且不依賴輸入是排列。

相關文章

LeetCode 2523: Closest Prime Numbers in Range
·1 分鐘
LeetCode Medium Math Number-Theory Sieve Array
LeetCode 2523 解題筆記:篩出範圍內的質數,相鄰的兩個質數才可能是最接近的;也可以從 left 往右試除,找到差是 2 的雙生質數就停
LeetCode 2761: Prime Pairs With Target Sum
·1 分鐘
LeetCode Medium Math Number-Theory Sieve Enumeration Array
LeetCode 2761 解題筆記:篩出 < n 的質數,x 從小到大、只看到 n / 2,x 和 n - x 都是質數就是一對
LeetCode 3895: Count Digit Appearances
·1 分鐘
LeetCode Medium Math Array
LeetCode 3895 解題筆記:把每個數字轉成字串,數 digit 出現的次數加總
LeetCode 3828: Final Element After Subarray Deletions
·1 分鐘
LeetCode Medium Math Brainteaser Game-Theory Array
LeetCode 3828 解題筆記:Alice 第一步就能只留下頭或尾,所以至少拿到 max(頭, 尾);Bob 每次也能只留下目前的頭或尾,而 Alice 的一次刪除最多改變其中一端,所以答案就是 max(頭, 尾)
LeetCode 1040: Moving Stones Until Consecutive II
·1 分鐘
LeetCode Medium Sliding-Window Math Sorting Array
LeetCode 1040 解題筆記:最多步數 = 總空位 − 第一步會浪費掉的那一邊空隙;最少步數用長度 n 的視窗找最多石頭,n - 1 顆已連續、剩一顆在遠處時要特判成 2
LeetCode 3627: Maximum Median Sum of Subsequences of Size 3
·1 分鐘
LeetCode Medium Math Greedy Sorting Game-Theory Array
LeetCode 3627 解題筆記:排序後每次拿最大的兩個和最小的一個,中位數是第二大的;答案是從尾端往前每隔一個取,共 n / 3 個