统计数组中的逆数对个数
题目:在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。
示例 1:
输入: [7,5,6,4]
输出: 5
限制:
0 <= 数组长度 <= 50000
方法一、暴力破解,使用冒泡算法思维,遍历数组和每一个元素后面的数字比较,时间复杂段O(n*n),不需要额外开辟数组空间,空间复杂度O(1)。
方法二、使用归并排序的算法思维进行比较统计,采用了二分的迭代方式,复杂度是 logn,每次的迭代,需要对两个有序数组进行合并,这样的动作的时间复杂度是 O(n) ,因此,总的复杂度就是二者的乘积 O(nlogn),每次合并的操作都需要开辟基于数组的临时内存空间,所以空间复杂度为 O(n)。
方法一实现代码:
public int getCountByBubble(int[] arr){ int bubble_count = 0; for(int i = 0; i < arr.length-1;i++) { for(int j = i+1; j < arr.length; j++) { if(arr[i] > arr[j]) bubble_count++; } } return bubble_count; }
方法二实现代码:
public class ArrTest { public static int count = 0; /** * 统计数组逆数对个数 * 归并思想统计,计算时间复杂度O(nlogn),空间复杂度O(n) * @param arr * @return */ public int getCountByMerge(int[] arr){ int[] tmp = new int[arr.length]; customMergeSort(arr,tmp,0,arr.length-1); return count; } public void customMergeSort(int[] a,int[] tmp, int start,int end) { if(start < end) { int mid = (start + end) / 2; customMergeSort(a,tmp,start,mid); customMergeSort(a,tmp,mid + 1, end); customDoubleMerge(a,tmp,start,mid,end); } } public void customDoubleMerge(int[] a,int[] tmp, int left,int mid,int right) { int p1 = left, p2 = mid+1, k = left,m = mid; while(p1 <= m && p2 <= right) { if(a[p1] <= a[p2]) { tmp[k++] = a[p1++]; } else { tmp[k++] = a[p2++]; count = (m - p1 + 1) + count; } } while(p1 <= m){ tmp[k++] = a[p1++]; } while(p2 <= right) { tmp[k++] = a[p2++]; } for(int i = 0; i< k;i++) a[i] = tmp[i]; }
}