0775. Global and Local Inversions (M)

Global and Local Inversions (M)

题目

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: true
Explanation: There is 1 global inversion, and 1 local inversion.

Example 2:

Input: A = [1,2,0]
Output: false
Explanation: There are 2 global inversions, and 1 local inversion.

Note:

  • A will be a permutation of [0, 1, ..., A.length - 1].
  • A will 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;
    }
}
posted @ 2021-04-05 16:39  墨云黑  阅读(42)  评论(0编辑  收藏  举报