Title description
// 51. 数组中的逆序对
// 力扣
// 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两
// 个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对
// 的总数。
// 牛客
// 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数
// 字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。
// 并将P对1000000007取模的结果输出。 即输出P%1000000007
answer
暴力法 ///
// 最直观的的做法是两个for循环全部遍历比对一轮
// 但是这种做法时间复杂度无法通过。
// 力扣
// 无法通过
class Solution {
public int reversePairs(int[] nums) {
int count = 0;
if (nums.length < 2)
return 0;
for (int i = 0; i < nums.length; i++) {
for (int j = i + 1; j < nums.length; j++) {
if (nums[i] > nums[j])
count++;
}
}
return count;
}
}
归并排序法
// 牛客
// 根据题意,前大后小的两个数字构成一个逆序对。
// 直接写一个归并排序,在merge函数当nums[l]<nums[r]时,记录逆序对个数
// 运行时间:235ms
// 占用内存:33856KB
public class Solution {
int count = 0;
public int InversePairs(int[] nums) {
int[] temp = new int[nums.length];
mergesort(nums, 0, nums.length - 1, temp);
return count % 1000000007;
}
private void mergesort(int[] nums, int left, int right, int[] temp) {
if (left < right) {
int mid = (left + right) / 2;
mergesort(nums, left, mid, temp);
mergesort(nums, mid + 1, right, temp);
merge(nums, left, mid, right, temp);
}
}
private void merge(int[] nums, int left, int mid, int right, int[] temp) {
int l = left;
int r = mid + 1;
int t = 0;
// 之前一直是nums[l]<=nums[r],l右移如果出现了nums[l]>nums[r],
// 说明l到mid的数,跟nums[r]都组成逆序对。(归并排序,左子数组元
// 素排序后还会在左子数组,右子数组元素排序后还会在右子数组)
while (l <= mid && r <= right) {
if (nums[l] <= nums[r])
temp[t++] = nums[l++];
else {
temp[t++] = nums[r++];
count += mid - l + 1;
count = count % 1000000007;
}
}
while (l <= mid) {
temp[t++] = nums[l++];
}
while (r <= right) {
temp[t++] = nums[r++];
}
t = 0;
while (left <= right)
nums[left++] = temp[t++];
}
}
int count = 0;
public int InversePairs(int[] nums) {
int[] temp = new int[nums.length];
mergesort(nums, 0, nums.length - 1, temp);
return count % 1000000007;
}
private void mergesort(int[] nums, int left, int right, int[] temp) {
if (left < right) {
int mid = (left + right) / 2;
mergesort(nums, left, mid, temp);
mergesort(nums, mid + 1, right, temp);
merge(nums, left, mid, right, temp);
}
}
private void merge(int[] nums, int left, int mid, int right, int[] temp) {
int l = left;
int r = mid + 1;
int t = 0;
while (l <= mid && r <= right) {
if (nums[l] < nums[r])
temp[t++] = nums[l++];
else {
temp[t++] = nums[r++];
count += mid - l + 1; // 如果nums[r] > nums[l]
count = count % 1000000007;
}
}
while (l <= mid) {
temp[t++] = nums[l++];
}
while (r <= right) {
temp[t++] = nums[r++];
}
t = 0;
while (left <= right)
nums[left++] = temp[t++];
}
}
// 力扣
// 执行用时:37 ms, 在所有 Java 提交中击败了61.83%的用户
// 内存消耗:48.3 MB, 在所有 Java 提交中击败了37.82%的用户
class Solution {
public int count = 0;
public int reversePairs(int[] nums) {
int[] temp = new int[nums.length];
mergesort(nums, 0, nums.length - 1, temp);
return count;
}
private void mergesort(int[] nums, int left, int right, int[] temp) {
if (left< right) {
int mid = (left + right) / 2;
mergesort(nums, left, mid, temp);
mergesort(nums, mid + 1, right, temp);
merge(nums, left, mid, right, temp);
}
}
private void merge(int[] nums, int left, int mid, int right, int[] temp) {
int l = left;
int r = mid + 1;
int t = 0;
while (l <= mid && r <= right) {
if (nums[l] <= nums[r])
temp[t++] = nums[l++];
else {
temp[t++] = nums[r++];
count += mid - l + 1;
}
}
while (l <= mid)
temp[t++] = nums[l++];
while (r <= right)
temp[t++] = nums[r++];
t = 0;
while (left <= right)
nums[left++] = temp[t++];
}
}