• 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;
        }
    }
    
  • 相关阅读:
    并发编程 19—— 显式的Conditon 对象
    JVM实用参数——新生代垃圾回收
    设计模式 8 —— 适配器和外观模式
    并发编程 18—— 使用内置条件队列实现简单的有界缓存
    并发编程 17—— Lock
    Spring 事务管理 01 ——
    并发编程 16—— 线程池 之 原理二
    并发编程 15—— 线程池 之 原理一
    并发编程 14—— 线程池 之 整体架构
    java.util.logging.Logger 使用详解
  • 原文地址:https://www.cnblogs.com/mapoos/p/14618727.html
Copyright © 2020-2023  润新知