剑指 Offer 51. 数组中的逆序对

递归解法(超内存)

public class Algorithm {

    public static void main(String[] args) {

        int[] nums = {7,5,6,4};
        System.out.println(new Solution().reversePairs(nums));

    }
}

class Solution {

    int start = 0;

    public int reversePairs(int[] nums) {

        if (nums == null || nums.length == 0 || nums.length == 1){
            return 0;
        }

        int[] temp = new int[nums.length - 1];

        System.arraycopy(nums, start + 1, temp, 0, nums.length - 1);

        int res1 = reversePairs(temp);

        int res2 = 0;

        for (int i = start + 1; i < temp.length + 1; i++) {

            if (nums[start] > nums[i]){
                res2++;
            }
        }

        return res1 + res2;
    }
}

归并排序解法

注意:不能将方法定义为static,否则LeetCode不能识别

import java.util.Arrays;

public class Algorithm {

    public static void main(String[] args) {

        int[] nums = {4, 5, 6, 7};
        System.out.println(new Solution().reversePairs(nums));
    }
}

class Solution {

    /**
     * 定义全局变量res统计总的逆序对
     */
    int res = 0;

    public int reversePairs(int[] nums) {

        int[] temp = Arrays.copyOf(nums, nums.length);

        sort(nums, 0, nums.length - 1, temp);

        return res;
    }

    public void sort(int[] arr, int left, int right, int[] temp){

        if (left >= right){
            return;
        }

        int mid = left + (right - left) / 2;

        sort(arr, left, mid, temp);
        sort(arr, mid + 1, right, temp);

        if (arr[mid] > arr[mid + 1]) {
            merge(arr, left, mid, right, temp);
        }
    }

    public void merge(int[] arr, int left, int mid, int right, int[] temp) {

        int i = left;
        int j = mid + 1;

        System.arraycopy(arr, left, temp, left, right - left + 1);

        for (int n = left; n < right + 1; n++) {

            if (i == mid + 1){
                arr[n] = temp[j];
                j++;
            }
            else if (j == right + 1) {
                arr[n] = temp[i];
                i++;
            }
            else if (temp[i] <= temp[j]) {
                arr[n] = temp[i];
                i++;
            }
            else{
                arr[n] = temp[j];
                
                /**
                 * 只有当temp[i] > temp[j],也就是左边区间的元素比右边大时,才会有逆序对
                 * 此时,左边所有剩下的元素,都和右边当前元素形成逆序对
                 */
                res = res + mid - i + 1;
                j++;
            }
        }
    }
}

不使用全量变量,而是用函数的返回值来统计逆序对,少维护一个全局变量,做到函数式编程

import java.util.Arrays;

public class Algorithm {

    public static void main(String[] args) {

        int[] nums = {4, 5, 6, 7};
        System.out.println(new Solution().reversePairs(nums));
    }
}

class Solution {

    public int reversePairs(int[] nums) {

        int[] temp = Arrays.copyOf(nums, nums.length);

        return sort(nums, 0, nums.length - 1, temp);
    }

    public int sort(int[] arr, int left, int right, int[] temp){

        if (left >= right){
            return 0;
        }

        /**
         * 将res变量定义在函数内部,实现函数式编程
         */
        int res = 0;

        int mid = left + (right - left) / 2;

        res += sort(arr, left, mid, temp);
        res += sort(arr, mid + 1, right, temp);

        if (arr[mid] > arr[mid + 1]) {
            res += merge(arr, left, mid, right, temp);
        }

        return res;
    }

    public int merge(int[] arr, int left, int mid, int right, int[] temp) {

        int i = left;
        int j = mid + 1;
        
        int res = 0;

        System.arraycopy(arr, left, temp, left, right - left + 1);

        for (int n = left; n < right + 1; n++) {

            if (i == mid + 1){
                arr[n] = temp[j];
                j++;
            }
            else if (j == right + 1) {
                arr[n] = temp[i];
                i++;
            }
            else if (temp[i] <= temp[j]) {
                arr[n] = temp[i];
                i++;
            }
            else{
                arr[n] = temp[j];
                res = res + mid - i + 1;
                j++;
            }
        }

        return res;
    }
}

自底向上归并排序解法

import java.util.Arrays;

public class Algorithm {

    public static void main(String[] args) {

        int[] nums = {7,5,6,4};
        System.out.println(new Solution().reversePairs(nums));
    }
}

class Solution {

    public int reversePairs(int[] nums) {

        int[] temp = Arrays.copyOf(nums, nums.length);
        return sort(nums, temp);
    }

    public int sort(int[] arr, int[] temp){

        int size;
        int res = 0;
		
        //arr[i, i + size - 1]和arr[i + size, i + size + size - 1]
        for (size = 1; size < arr.length; size *= 2) {

            for (int i = 0; i + size < arr.length; i += 2 * size) {

                if (arr[i + size - 1] > arr[i + size]){
                    res += merge(arr, i, i + size - 1, Math.min(i + 2 * size - 1, arr.length - 1), temp);
                }
            }
        }

        return res;
    }

    public int merge(int[] arr, int left, int mid, int right, int[] temp) {

        int i = left;
        int j = mid + 1;
        int res = 0;

        System.arraycopy(arr, left, temp, left, right - left + 1);

        for (int n = left; n < right + 1; n++) {

            if (i == mid + 1){
                arr[n] = temp[j];
                j++;
            }
            else if (j == right + 1) {
                arr[n] = temp[i];
                i++;
            }
            else if (temp[i] <= temp[j]) {
                arr[n] = temp[i];
                i++;
            }
            else{
                arr[n] = temp[j];
                res += mid - i + 1;
                j++;
            }
        }

        return res;
    }
}

https://leetcode-cn.com/problems/shu-zu-zhong-de-ni-xu-dui-lcof/