题目
We have some permutation A of [0, 1, ..., N - 1], where N is the length of A.
The number of (global) inversions is the number of i < j with 0 <= i < j < N and A[i] > A[j].
The number of local inversions is the number of i with 0 <= i < N and A[i] > A[i+1].
Return true if and only if the number of global inversions is equal to the number of local inversions.
Example 1:
Input: A = [1,0,2]Output: trueExplanation: There is 1 global inversion, and 1 local inversion.
Example 2:
Input: A = [1,2,0]Output: falseExplanation: There are 2 global inversions, and 1 local inversion.
Note:
Awill be a permutation of[0, 1, ..., A.length - 1].Awill have length in range[1, 5000].- The time limit for this problem has been reduced.
题意
给定一个数组,如果 i < j 且 A[i] > A[j],则称存在一个全局倒置;如果 A[i] > A[i+1],则称存在一个局部倒置。判断全局倒置的数量是否和局部倒置相同。
思路
最直接的方法是计算局部倒置和全局倒置(归并排序中判断),并进行比较。
用到题目给的条件:A是 0 ~ N-1 的一个排列,如果不存在倒置,A = [0, 1, 2, 3, …, N-1],如果存在倒置,相当于在这个递增数组中选两个元素互换。局部倒置一定是全局倒置,如果两者数量相等,则所有全局倒置也一定是局部倒置,相当于在这个递增数组中仅选取相邻的元素进行互换,因此只要遍历一遍数组,判断 A[i] 的值是否在 (i - 1, i, i + 1)中即可。
代码实现
Java
直接计算
class Solution {public boolean isIdealPermutation(int[] A) {return calcLocal(A) == calcGlobal(A);}private int calcLocal(int[] A) {int local = 0;for (int i = 0; i < A.length - 1; i++) {if (A[i] > A[i + 1]) {local++;}}return local;}private int calcGlobal(int[] A) {int global = 0;for (int step = 1; step < A.length; step *= 2) {for (int start = 0; start + step < A.length; start += 2 * step) {int left = start, leftEnd = left + step - 1;int right = start + step, rightEnd = Math.min(A.length - 1, right + step - 1);int[] tmp = new int[rightEnd - left + 1];int index = 0;while (left <= leftEnd || right <= rightEnd) {if (left > leftEnd || right > rightEnd) {tmp[index++] = left > leftEnd ? A[right++] : A[left++];} else if (A[left] <= A[right]){tmp[index++] = A[left++];} else {global += leftEnd - left + 1;tmp[index++] = A[right++];}}for (int i = start; i <= rightEnd; i++) {A[i] = tmp[i - start];}}}return global;}}
遍历判断
class Solution {public boolean isIdealPermutation(int[] A) {for (int i = 0; i < A.length; i++) {if (Math.abs(A[i] - i) > 1) return false;}return true;}}
