
这题和归并排序联系紧密,使用归并排序时比较前后两个区间中的数,由于这两个区间都是升序的,因此如果左区间的一个数大于右区间的一个数,那么左区间的该数以及其右边的数全都大于右区间的此数,即mid - i + 1个逆序对,因为归并特性,该右区间的数不会再碰到此逆序对中的任何一个数,证明了此方法的正确性
注:使用归并如果temp数组如果写在merge方法中,创建多次temp数组此题会超时,可以将temp数组作为一个公共数组传参。
class Solution {
int count = 0;
public int reversePairs(int[] nums) {
//O(m*n)复杂度太高,使用归并排序刚好符合此题特点
if(nums.length == 0) return 0;
int[] temp = new int[nums.length];
mergeSort(nums, 0, nums.length-1,temp);
return count;
}
void mergeSort(int[] nums,int low,int high,int[] temp){
if(low == high) return;
else{
int mid = (low + high) / 2;
mergeSort(nums,low,mid,temp);
mergeSort(nums,mid + 1,high,temp);
merge(nums,low,mid,high,temp);
}
}
private void merge(int[] nums, int low, int mid, int high,int[] temp) {
int i = low,j = mid + 1;
int m = mid,n = high;
int k = 0;
while(i <= m && j <= n){
if(nums[i] <= nums[j]) temp[k++] = nums[i++];
else{
count += (mid - i + 1); //归并排序加上此行 比如2 4 6 和 1 3 5 指针指向2和1时,2比1大,说明2后面数字也一定比1大,所以对于数字1作为较小值的逆序对数量是46,归并后它们的数字不会再相会,证明这个方法的正确性
temp[k++] = nums[j++];
}
}
while(i <= m){
temp[k++] = nums[i++];
}
while(j <= n){
temp[k++] = nums[j++];
}
for(int x = low;x <= high;x++){
nums[x] = temp[x - low];
}
}
}
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)