Medium
题目描述
给你一个长度为 n 的整数数组 nums,表示由范围 [0, n - 1] 内所有整数组成的一个排列。
全局倒置 的数目等于满足下述条件不同数对 (i, j) 的数目:
0 <= i < j < nnums[i] > nums[j]
局部倒置 的数目等于满足下述条件的下标 i 的数目:
0 <= i < n - 1nums[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.length1 <= n <= 10^50 <= nums[i] < nnums中的所有整数 互不相同nums是范围[0, n - 1]内所有数字组成的一个排列
解题思路
解题思路
关键观察
首先需要理解全局倒置和局部倒置的关系:
- 局部倒置:相邻元素的逆序对
(i, i+1) - 全局倒置:所有的逆序对
(i, j)其中i < j
重要发现:每个局部倒置都是全局倒置,因为如果 nums[i] > nums[i+1],那么 (i, i+1) 既是局部倒置也是全局倒置。
解法分析
方法一:直接计算(会超时) 暴力计算全局倒置和局部倒置的数量进行比较,时间复杂度 O(n²)。
方法二:数学推理(推荐) 由于局部倒置 ⊆ 全局倒置,当且仅当不存在"非局部的全局倒置"时,两者数量相等。
非局部的全局倒置指:存在 i < j 且 j > i + 1,使得 nums[i] > nums[j]。
因此问题转化为:检查是否存在 i 和 j,满足 j >= i + 2 且 nums[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) |