归并排序
数组中的逆序对
https://www.nowcoder.com/practice/96bd6684e04a44eb80e6a68efc0ec6c5?tpId=13&tqId=11188&tPage=2&rp=2&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking
归并排序(复杂度O(n log n))
该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。
归并排序是一种稳定的排序方法。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为2-路归并。
算法描述
1、把长度为n的输入序列分成两个长度为n/2的子序列;
2、对这两个子序列分别采用归并排序;
3、将两个排序好的子序列合并成一个最终的排序序列。
代码实现
// 归并排序
public static int[] MergeSort(int[] array) {
if (array.length < 2) return array;
int mid = array.length / 2;
int[] left = Arrays.copyOfRange(array, 0, mid);
int[] right = Arrays.copyOfRange(array, mid, array.length);
return merge(MergeSort(left), MergeSort(right));
}
public static int[] merge(int[] left, int[] right) {
int[] result = new int[left.length + right.length];
for (int index = 0, i = 0, j = 0; index < result.length; index++) {
if (i >= left.length)
result[index] = right[j++];
else if (j >= right.length)
result[index] = left[i++];
else if (left[i] > right[j])
result[index] = right[j++];
else
result[index] = left[i++];
}
return result;
}
题目:逆序数(剑指offer)
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。 即输出P%1000000007
题解:[A,B]中的逆序对=[A]的逆序对+[B]中的逆序对+将A,B混排在一起的逆序对
代码实现:
public class Solution {
private int cnt;
private void MergeSort(int[] array, int start, int end) {
if (start >= end) return;
int mid = (start + end) / 2;
MergeSort(array, start, mid);
MergeSort(array, mid + 1, end);
MergeOne(array, start, mid, end);
}
private void MergeOne(int[] array, int start, int mid, int end) {
int[] tmp = new int[end - start + 1];
int k = 0, i = start, j = mid + 1;
while (i <= mid && j <= end) {
if (array[i] <= array[j]) {
//如果前面的元素小于后面的饿,则不也能构成逆序对
tmp[k++] = array[i++];
} else {
//如果前面的元素大于后面的,那么在前面元素之后的元素都能和后面的元素构成逆序对
tmp[k++] = array[j++];
cnt = (cnt + mid + 1 - i) % 1000000007;
}
}
while (i <= mid) tmp[k++] = array[i++];
while (j <= end) tmp[k++] = array[j++];
for (int l = 0; l < k; l++) {
array[l + start] = tmp[l];
}
}
public int InversePairs(int[] array) {
MergeSort(array, 0, array.length - 1);
return cnt;
}
}