在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。 即输出P mod 1000000007
数据范围: 对于
对于
数组中所有数字的值满足 
要求:空间复杂度
,时间复杂度
题目保证输入的数组中没有的相同的数字
[1,2,3,4,5,6,7,0]
7
[1,2,3]
0
public class Solution {
private static long count = 0;
private static final int MOD = 1000000007;
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param nums int整型一维数组
* @return int整型
*/
public int InversePairs (int[] nums) {
// write code here
if(nums == null || nums.length < 2){
return 0;
}
mergeSortCalc(nums, 0, nums.length - 1);
return (int)(count % MOD);
}
public static void mergeSortCalc(int[] arr, int left, int right){
if(left >= right){
return;
}
int mid = left + (right - left)/2;
mergeSortCalc(arr, left, mid);
mergeSortCalc(arr, mid + 1, right);
mergeArray(arr, left, mid, right);
}
private static void mergeArray(int[] arr, int left, int mid, int right){
int[] temp = new int[right - left + 1];
int i = left, j = mid + 1, k = 0;
while(i <= mid && j <= right){
if(arr[i] < arr[j]){
temp[k++] = arr[i++];
} else {
temp[k++] = arr[j++];
// 核心:左半部分i到mid的所有元素都比arr[j]大,都是逆序对
count += (mid - i + 1);
count %= MOD; // 提前取模,避免数值溢出
}
}
while(i <= mid){
temp[k++] = arr[i++];
}
while(j<=right){
temp[k++] = arr[j++];
}
for(int p = 0;p<temp.length;p++){
arr[left + p] = temp[p];
}
}
} java用普通的归并排序顺便计算逆序对数
public class Solution {
private static long count = 0;
public int InversePairs (int[] nums) {
// write code here
count = 0;
Sort(nums);
return (int)(count % 1000000007);
}
public static void Sort(int[] arr) {
Sort(arr, 0, arr.length - 1);
}
public static void Sort(int[] arr, int l, int r) {
if (l >= r) {
return;
}
int mid = l + (r - l) / 2;
Sort(arr, l, mid);
Sort(arr, mid + 1, r);
if (arr[mid] > arr[mid + 1]) {
merge(arr, l, mid, r);
}
}
private static void merge(int[] arr, int l, int mid, int r) {
int[] temp = Arrays.copyOfRange(arr, l, r + 1);
int i = l, j = mid + 1;
for (int k = l; k <= r; k++) {
if (i > mid) {
arr[k] = temp[j - l];
j++;
} else if (j > r) {
arr[k] = temp[i - l];
i++;
} else if (temp[i - l]<temp[j - l]) {
arr[k] = temp[i - l];
i++;
} else {
arr[k] = temp[j - l];
j++;
count=count+(mid-i+1);
}
}
}
} import java.util.*;
// @@@ 题解:归并排序
public class Solution {
private int res = 0;
private int mod = 1000000007;
public int InversePairs (int[] nums) {
// write your answer here
mergeSort(nums, 0, nums.length - 1); // 归并排序
// for (int i = 0; i < n; i++) System.out.print(nums[i] + " ");
return res;
}
// 归并排序
private void mergeSort(int[] nums, int l, int r) {
if (l == r) return;
int mid = (l + r) / 2;
mergeSort(nums, l, mid); // 分左半数组
mergeSort(nums, mid + 1, r); // 分右半数组
merge(nums, l, mid, r); // 合并
}
// 合并
private void merge(int[] nums, int l, int mid, int r) {
int[] a = new int[r - l + 1]; // 临时数组
int i = l, j = mid + 1, k = 0;
while (i <= mid && j <= r) {
if (nums[i] > nums[j]) {
res = (res + r - j + 1) % mod; // 逆序🍓【奥妙之处】
a[k++] = nums[i++];
} else {
a[k++] = nums[j++];
}
}
while (i <= mid) a[k++] = nums[i++]; // 剩余的
while (j <= r) a[k++] = nums[j++];
for (i = l, j = 0; i <= r; i++, j++) nums[i] = a[j]; // 复制到原数组
}
} // 暴力解法
public int InversePairs1 (int[] nums) {
long count = 0;
for(int i=0;i<nums.length-1;i++){
for(int j = i+1;j<nums.length;j++){
if(nums[i] > nums[j]){
count++;
}
}
}
return (int)(count % 1000000007);
}
// 插入排序
public int InversePairs2 (int[] nums) {
long count = 0;
ArrayList<Integer> list = new ArrayList<>();
list.add(nums[nums.length-1]);
for(int i=nums.length-2;i >= 0;i--){
count += InversePairs_insert(list,nums[i]);
}
return (int)(count % 1000000007);
}
public int InversePairs_insert (ArrayList<Integer> list,int data) {
int s=0,e=list.size()-1;
int mid = 0;
while(s<=e){
mid = (s+e)/2;
if(list.get(mid) == data){
break;
}else if(list.get(mid) > data){
e = mid - 1;
}else{
s = mid + 1;
}
}
if(s > mid){
list.add(mid+1,data);
return mid + 1;
}else{
list.add(mid,data);
return mid;
}
}
// 归并
public int InversePairs (int[] nums) {
if(nums.length < 2) return 0;
int[] temp = new int[nums.length];
int count = InversePairs_sort(nums,0,nums.length-1,temp);
return count;
}
public int InversePairs_sort(int[] nums,int s,int e,int[] temp) {
if(s >= e) return 0;
int mid = (s+e)/2;
int res = InversePairs_sort(nums,s,mid,temp)
+ InversePairs_sort(nums,mid+1,e,temp);
res = res % 1000000007;
int i = s,j = mid+1;
for(int k=s;k<=e;k++){
temp[k] = nums[k];
}
for(int k=s;k<=e;k++){
if(i == mid+1){
nums[k] = temp[j++];
}else if(j == e+1 || temp[i] <= temp[j]){
nums[k] = temp[i++];
}else{
nums[k] = temp[j++];
res += mid - i + 1;
}
}
return res % 1000000007;
} import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param nums int整型一维数组
* @return int整型
*/
public int InversePairs (int[] nums) {
// write code here
// 左程云老师讲过,通过归并排序过程中的左右两个字串的比较,可以实现逆序对的统计
// 算法的时间复杂度O(NlogN),空间复杂度O(N)
// 调用归并排序的递归执行方法
int count = process(nums, 0, (nums.length - 1));
// 注意题目要求,对1000000007取模
return count % 1000000007;
}
// 递归执行方法
public int process(int[] nums, int l, int r) {
// 递归出口
if (l == r) {
return 0;
}
// 计算中间索引
int mid = (l + r) / 2;
// 返回递归过程产生的逆序对数量
int count = process(nums, l, mid) +
process(nums, mid + 1, r) +
compareAndMerge(nums, l, mid, r);
// 注意题目要求,对1000000007取模
return count % 1000000007;
}
// 比较与归并方法
public int compareAndMerge(int[] nums, int l, int mid, int r) {
// 记录逆序对的个数
int count = 0;
// 比较,归并
int[] tempNums = new int[r - l + 1];
// nums的左半区下标
int leftIndex = l;
// nums的右半区下标
int rightIndex = mid + 1;
// tempNums的下标
int tempIndex = 0;
while (leftIndex <= mid && rightIndex <= r) {
// 请注意,归并排序merge的一个前提是,左右两个半区各自有序
if (nums[leftIndex] < nums[rightIndex]) {
// 左边 < 右边,则左边先进入tempNums中,leftIndex和tempIndex都++
tempNums[tempIndex] = nums[leftIndex];
leftIndex++;
} else {
// 左边 > 右边,则右边先进入tempNums中,rightIndex和tempIndex都++
// 注意!此时算作逆序对!
tempNums[tempIndex] = nums[rightIndex];
rightIndex++;
// tempNums[leftIndex]大,说明从leftIndex到mid上的数都更大,逆序数要全算上
count += (mid - leftIndex + 1);
// 注意题目要求,对1000000007取模
count %= 1000000007;
}
tempIndex++;
}
// 此时退出了循环,要么leftIndex越界,要么rightIndex越界,以下两个while最多执行一个
while (leftIndex <= mid) {
// 右边的rightIndex先越界了,说明左边剩下的元素都比右边的大,把左边剩下的元素全部送进tempNums中
// 注意!这里的逆序对已经被上一个while中考虑到了
tempNums[tempIndex] = nums[leftIndex];
leftIndex++;
tempIndex++;
}
while (rightIndex <= r) {
// 左边的leftIndex先越界了,说明右边剩下的元素都比左边的大,把右边剩下的元素全部送进tempNums中
tempNums[tempIndex] = nums[rightIndex];
rightIndex++;
tempIndex++;
}
// 最后,把tempNums排好序的内容写回nums的对应位置
for (int i = 0; i < tempNums.length; i++) {
nums[l + i] = tempNums[i];
}
// 返回统计到的逆序数
return count;
}
} public class Solution {
public int InversePairs(int[] nums) {
int left = 0, right = nums.length - 1;
return (int)(mergeSort(nums, left, right) % 1000000007);
}
private long mergeSort(int[] nums, int left, int right) {
if (left == right) {
return 0;
}
int mid = left + ((right - left) >> 1);
long x1 = mergeSort(nums, left, mid);
long x2 = mergeSort(nums, mid + 1, right);
long x3 = merge(nums, left, mid, mid + 1, right);
return x1 + x2 + x3;
}
private long merge(int[] nums, int l1, int l2, int r1, int r2) {
int[] temp = new int[r2 - l1 + 1];
int i = 0;
int l = l1;
long count = 0;
while (l1 <= l2 && r1 <= r2) {
if (nums[l1] > nums[r1]) {
count = count + r2 - r1 + 1;
temp[i++] = nums[l1++];
} else {
temp[i++] = nums[r1++];
}
}
while (l1 <= l2) {
temp[i++] = nums[l1++];
}
while (r1 <= r2) {
temp[i++] = nums[r1++];
}
// 放回原来的数组
i = 0;
for (int i1 = l; i1 <= r2; i1++) {
nums[i1] = temp[i++];
}
return count;
}
}
归并排序
public class Solution {
public static final int MOD = 1000000007;
public int InversePairs (int[] nums) {
return mergeSort(nums, 0, nums.length - 1);
}
public int mergeSort(int[] nums, int l, int r) {
if (l == r) {
return 0;
}
int mid = (l + r) >> 1;
int lres = mergeSort(nums, l, mid);
int rres = mergeSort(nums, mid + 1, r);
int left = l, right = mid + 1, ans = (lres + rres) % MOD;
int[] tmp = new int[r - l + 1];
int idx = 0;
while (left <= mid && right <= r) {
if (nums[left] <= nums[right]) {
tmp[idx++] = nums[left++];
} else {
tmp[idx++] = nums[right++];
ans = (ans + mid - left + 1) % MOD;
}
}
while (left <= mid) tmp[idx++] = nums[left++];
while (right <= r) tmp[idx++] = nums[right++];
for (int i = 0; i < idx; i++) {
nums[l + i] = tmp[i];
}
return ans;
}
}
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param nums int整型一维数组
* @return int整型
*/
public int InversePairs (int[] nums) {
long total=0;
for (int i = 0; i < nums.length; i++) {
for (int j = i+1; j <nums.length; j++) {
if (nums[i]>nums[j]){
total++;
}
}
}
return (int) (total%1000000007);
}
} public class Solution {
public int InversePairs(int [] array) {
if (array == null || array.length == 0) return -1;
int count = 0;
for (int i = 0; i < array.length - 1; i++) {
for (int j = i; j < array.length - 1; j++) {
if (array[i] > array[j + 1]) count++;
}
}
return count % 1000000007;
}
} public class Solution {
public int InversePairs(int [] array) {
if(array.length == 0) return 0;
long P =0L;
for(int i =0; i < array.length - 1; i++)
for(int j = i + 1; j < array.length; j++){
if(array[i] > array[j]) P++;
}
return (int)(P % 1000000007);
}
} 这个代码是不是时间复杂度是O(n^2)?虽然通过了,冒泡排序再怎么优化都是n^2吗?