题目描述
题目来源:剑指
Offer 51. 数组中的逆序对 - 力扣(LeetCode) (leetcode-cn.com)
数组中的逆序对是数据结构和算法中的一道经典题目。如果A[i]>A[j]
并且i<j
,那么这就算是一组逆序对。题目要求给定一个数组,求出数组中逆序对的个数
输入:[7,5,6,4]
输出:5
题解
本题可以使用排序的思想,因为在排序中我们发现的不符合排列顺序的数组对都是一组逆序对,我们只需要计算出在排序的过程中交换的次数即可。本题中可以采用时间复杂度为O(logn)的归并排序。代码如下:
基本思路和归并排序是一样的,如果对归并排序的代码不理解的可以先看一看排序算法。
唯一需要注意的地方就是归并的时候的逆序对计算,当我们发现right小于left的时候,right同时也小于left后面的所有元素,我们增加的个数就是mid-left+1(merge函数)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| class Solution {
private static int[] aux;
public int reversePairs(int[] nums) { if (nums.length < 2) return 0; aux = new int[nums.length]; return subReversePairs(nums, 0, nums.length - 1); }
private int subReversePairs(int[] nums, int lo, int hi) { if (lo >= hi) return 0; int mid = lo + (hi - lo) / 2; int count = 0; count += subReversePairs(nums, lo, mid); count += subReversePairs(nums, mid+1, hi); if (nums[mid] <= nums[mid+1]) return count; count += merge(nums, lo, mid, hi); return count; }
private int merge(int[] nums, int lo, int mid, int hi) { int count = 0; for (int i = lo; i <= hi; i++) aux[i] = nums[i]; int left = lo, right = mid+1, index = lo; while (left <= mid && right <= hi) { if (aux[left] <= aux[right]) nums[index++] = aux[left++]; else if (aux[left] > aux[right]) { nums[index++] = aux[right++]; count += mid - left + 1; } } while (left <= mid) nums[index++] = aux[left++]; while (right <= hi) nums[index++] = aux[right++]; return count; } }
|