方法一:树状数组
懒人解法,经典求解逆序对数量。a记录局部倒置数量,b记录全局倒置数量,最后判断a、b是否相等即可。因为会爆int,而且注意到a最大值是n-1(n为数组长度),所以在遍历的时候,当b>=n了即可返回false。
class Solution {
public:
int tr[100010];
int n;
int lowbit(int x){
return x&-x;
}
void add(int x,int k){
for(int i=x;i<=n;i+=lowbit(i)) tr[i]+=k;
}
int query(int x){
int res=0;
for(int i=x;i;i-=lowbit(i)) res+=tr[i];
return res;
}
bool isIdealPermutation(vector<int>& nums) {
n=nums.size();
int a=0,b=0;
for(int i=n-1;~i;i--){
if(i&&nums[i]<nums[i-1]) a++;
b+=query(nums[i]+1);
if(b>=n) return 0;
add(nums[i]+1,1);
}
return a==b;
}
};
时间复杂度:O(nlogn)
空间复杂度:O(n)
方法二:数学
容易猜到结论,对于一个排序好的数组,必然是满足条件的。但是如果一个数在位置i处,而排序后它在j处,且abs(i-j)>1,说明它的偏移量超过了1,那么必然有全局>=局部,数组一定不满足条件。
class Solution {
public:
bool isIdealPermutation(vector<int>& nums) {
for (int i=0;i<nums.size();i++) {
if (abs(nums[i]-i)>1) {
return 0;
}
}
return 1;
}
};
时间复杂度:O(n)
空间复杂度:O(1)