本问题对应的 leetcode 原文链接:剑指 Offer 51. 数组中的逆序对

问题描述

在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。

示例1 :

输入: [7,5,6,4]
输出: 5

限制:

0 <= 数组长度 <= 50000

解题思路

视频讲解直达: 本题视频讲解

代码实现

class Solution {
    public int reversePairs(int[] nums) {
        if(nums == null || nums.length <= 1){
            return 0;
        }
        return mergeSort(nums, 0, nums.length - 1);
    }

    int mergeSort(int[] nums, int left, int right){
        if(left >= right){
            return 0;
        }
        int mid = (right - left) / 2 + left;
        int x1 = mergeSort(nums, left, mid);
        int x2 = mergeSort(nums, mid + 1, right);
        int x3 = merge(nums, left, mid, mid+1, right);

        return x1 + x2 + x3;
    }

    int merge(int[] nums, int l1, int r1, int l2, int r2){
        int[] temp = new int[r2 - l1 + 1];
        int count = 0;
        int i = l1, j = l2, k = 0;
        while(i <= r1 && j <= r2){
            if(nums[i] > nums[j]){
                count = count + (l2 - i);
                temp[k++] = nums[j++];
            }else{
                temp[k++] = nums[i++];
            }
        }
        while(i <= r1) temp[k++] = nums[i++];
        while(j <= r2) temp[k++] = nums[j++];

        // 把临时数组复制回原数组
        k = 0;
        for(i = l1; i <= r2; i++){
            nums[i] = temp[k++];
        }

        return count;
    }
}

复杂度和归并排序一样
时间:O(nlogn)
空间:O(n)

Python

class Solution(object):
    def reversePairs(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        if not nums or len(nums) <= 1:
            return 0

        def mergeSort(left, right):
            if left >= right:
                return 0

            mid = (right - left) // 2 + left
            x1 = mergeSort(left, mid)
            x2 = mergeSort(mid + 1, right)

            i, j = left, mid + 1
            temp = []
            count = 0

            while i <= mid and j <= right:
                if nums[i] > nums[j]:
                    count += mid - i + 1
                    temp.append(nums[j])
                    j += 1
                else:
                    temp.append(nums[i])
                    i += 1

            while i <= mid:
                temp.append(nums[i])
                i += 1

            while j <= right:
                temp.append(nums[j])
                j += 1

            nums[left:right+1] = temp

            return x1 + x2 + count

        return mergeSort(0, len(nums) - 1)

C++

class Solution {
public:
    int reversePairs(vector<int>& nums) {
        if (nums.empty() || nums.size() <= 1)
            return 0;

        function<int(int, int)> mergeSort;
        mergeSort = [&](int left, int right) -> int {
            if (left >= right)
                return 0;

            int mid = left + (right - left) / 2;
            int x1 = mergeSort(left, mid);
            int x2 = mergeSort(mid + 1, right);

            int i = left, j = mid + 1;
            int count = 0;
            vector<int> temp;

            while (i <= mid && j <= right) {
                if (nums[i] > nums[j]) {
                    count += mid - i + 1;
                    temp.push_back(nums[j]);
                    j++;
                } else {
                    temp.push_back(nums[i]);
                    i++;
                }
            }

            while (i <= mid) {
                temp.push_back(nums[i]);
                i++;
            }

            while (j <= right) {
                temp.push_back(nums[j]);
                j++;
            }

            for (int k = left; k <= right; k++) {
                nums[k] = temp[k - left];
            }

            return x1 + x2 + count;
        };

        return mergeSort(0, nums.size() - 1);
    }
};

Go

func reversePairs(nums []int) int {
    if len(nums) == 0 || len(nums) == 1 {
        return 0
    }

    var mergeSort func(int, int) int
    mergeSort = func(left, right int) int {
        if left >= right {
            return 0
        }

        mid := left + (right - left) / 2
        x1 := mergeSort(left, mid)
        x2 := mergeSort(mid + 1, right)

        i, j := left, mid + 1
        count := 0
        temp := make([]int, 0, right - left + 1)

        for i <= mid && j <= right {
            if nums[i] > nums[j] {
                count += mid - i + 1
                temp = append(temp, nums[j])
                j++
            } else {
                temp = append(temp, nums[i])
                i++
            }
        }

        for i <= mid {
            temp = append(temp, nums[i])
            i++
        }

        for j <= right {
            temp = append(temp, nums[j])
            j++
        }

        copy(nums[left:right+1], temp)

        return x1 + x2 + count
    }

    return mergeSort(0, len(nums) - 1)
}

JS

/**
 * @param {number[]} nums
 * @return {number}
 */
var reversePairs = function(nums) {
    if (nums == null || nums.length <= 1) {
        return 0;
    }
    return mergeSort(nums, 0, nums.length - 1);
};

function mergeSort(nums, left, right) {
    if (left >= right) {
        return 0;
    }
    let mid = Math.floor((right - left) / 2 + left);
    let x1 = mergeSort(nums, left, mid);
    let x2 = mergeSort(nums, mid + 1, right);
    let x3 = merge(nums, left, mid, mid + 1, right);

    return x1 + x2 + x3;
}

function merge(nums, l1, r1, l2, r2) {
    let temp = new Array(r2 - l1 + 1);
    let count = 0;
    let i = l1,
        j = l2,
        k = 0;
    while (i <= r1 && j <= r2) {
        if (nums[i] > nums[j]) {
            count = count + (l2 - i);
            temp[k++] = nums[j++];
        } else {
            temp[k++] = nums[i++];
        }
    }
    while (i <= r1) temp[k++] = nums[i++];
    while (j <= r2) temp[k++] = nums[j++];

    // 把临时数组复制回原数组
    k = 0;
    for (i = l1; i <= r2; i++) {
        nums[i] = temp[k++];
    }

    return count;
}

发表回复

后才能评论