Medium

题目描述

给你一个长度为 n 的整数数组 nums,表示由范围 [0, n - 1] 内所有整数组成的一个排列。

全局倒置 的数目等于满足下述条件不同数对 (i, j) 的数目:

  • 0 <= i < j < n
  • nums[i] > nums[j]

局部倒置 的数目等于满足下述条件的下标 i 的数目:

  • 0 <= i < n - 1
  • nums[i] > nums[i + 1]

当数组 nums全局倒置 的数量等于 局部倒置 的数量时,返回 true;否则,返回 false

示例 1:

输入:nums = [1,0,2]
输出:true
解释:有 1 个全局倒置,也有 1 个局部倒置。

示例 2:

输入:nums = [1,2,0]
输出:false
解释:有 2 个全局倒置,1 个局部倒置。

提示:

  • n == nums.length
  • 1 <= n <= 10^5
  • 0 <= nums[i] < n
  • nums 中的所有整数 互不相同
  • nums 是范围 [0, n - 1] 内所有数字组成的一个排列

解题思路

解题思路

关键观察

首先需要理解全局倒置和局部倒置的关系:

  • 局部倒置:相邻元素的逆序对 (i, i+1)
  • 全局倒置:所有的逆序对 (i, j) 其中 i < j

重要发现:每个局部倒置都是全局倒置,因为如果 nums[i] > nums[i+1],那么 (i, i+1) 既是局部倒置也是全局倒置。

解法分析

方法一:直接计算(会超时) 暴力计算全局倒置和局部倒置的数量进行比较,时间复杂度 O(n²)。

方法二:数学推理(推荐) 由于局部倒置 ⊆ 全局倒置,当且仅当不存在"非局部的全局倒置"时,两者数量相等。

非局部的全局倒置指:存在 i < jj > i + 1,使得 nums[i] > nums[j]

因此问题转化为:检查是否存在 ij,满足 j >= i + 2nums[i] > nums[j]

方法三:位置约束分析 由于 nums[0, n-1] 的排列,理想情况下每个数字 k 应该在位置 k 附近。通过数学分析可以证明:当且仅当每个位置 i 上的数字与 i 的差的绝对值不超过 1 时,全局倒置数等于局部倒置数。

即:|nums[i] - i| <= 1 对所有 i 成立。

代码实现

class Solution {
public:
    bool isIdealPermutation(vector<int>& nums) {
        for (int i = 0; i < nums.size(); i++) {
            if (abs(nums[i] - i) > 1) {
                return false;
            }
        }
        return true;
    }
};
class Solution:
    def isIdealPermutation(self, nums: List[int]) -> bool:
        for i in range(len(nums)):
            if abs(nums[i] - i) > 1:
                return False
        return True
public class Solution {
    public bool IsIdealPermutation(int[] nums) {
        for (int i = 0; i < nums.Length; i++) {
            if (Math.Abs(nums[i] - i) > 1) {
                return false;
            }
        }
        return true;
    }
}
var isIdealPermutation = function(nums) {
    for (let i = 0; i < nums.length; i++) {
        if (Math.abs(nums[i] - i) > 1) {
            return false;
        }
    }
    return true;
};

复杂度分析

复杂度类型大小
时间复杂度O(n)
空间复杂度O(1)