困难-剑指offer51-数组中的逆序对
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。
示例 1:
输入: [7,5,6,4]
输出: 5
限制:
0 <= 数组长度 <= 50000
线段树的思路还没看,先写归并排序
将大数组递归至小数组开始合并,在合并left数组和right数组时,此时两数组内部的逆序对已经计算过,只需计算两数组间的逆序对,因此合并left数组时,无需加值,而合并right数组时加上left数组中为合并的元素个数即可。
class Solution { public int reversePairs(int[] nums) { int len = nums.length; if(len<2) return 0; int[] copy = new int[len]; for(int i=0; i<len; i++) copy[i] = nums[i]; int[] temp = new int[len]; return reversePairs(nums,0,len-1,temp); } public int reversePairs(int[] nums, int left, int right, int[] temp) { if(left == right) return 0; int mid = left + (right - left) / 2; int leftPairs = reversePairs(nums,left,mid,temp); int rightPairs = reversePairs(nums,mid+1, right, temp); if(nums[mid]<=nums[mid+1]) return leftPairs + rightPairs; int crossPairs = mergeAndCount(nums,left,mid,right,temp); return leftPairs + rightPairs + crossPairs; } public int mergeAndCount(int[] nums, int left, int mid, int right, int[] temp) { for(int i=left; i<=right; i++){ temp[i] = nums[i]; } int i=left; int j=mid+1; int count = 0; for(int k=left; k<=right; k++){ if(i==mid+1){ nums[k] = temp[j]; j++; } else if (j==right+1){ nums[k] = temp[i]; i++; } else if(temp[i]<=temp[j]){ nums[k] = temp[i]; i++; } else { nums[k] = temp[j]; j++; count += (mid-i+1); } } return count; } }