在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。 即输出P mod 1000000007
数据范围: 对于
对于
数组中所有数字的值满足 
要求:空间复杂度
,时间复杂度
题目保证输入的数组中没有的相同的数字
[1,2,3,4,5,6,7,0]
7
[1,2,3]
0
function InversePairs(data)
{
let count = 0
if (!Array.isArray(data) || data.length < 2){
return count
}
// 以下两个箭头函数构成一个归并排序
const merge = (left, right) => {
const arr = []
while (left.length && right.length) {
if (left[0] > right[0]) {
arr.push(right.shift())
count += left.length
} else {
arr.push(left.shift())
}
}
left.length && arr.push(...left)
right.length && arr.push(...right)
return arr
}
const mergeSort = (arr) => {
if (arr.length < 2) {
return arr
}
const middle = Math.ceil(arr.length / 2)
const leftPart = arr.slice(0, middle)
const rightPart = arr.slice(middle)
return merge(mergeSort(leftPart), mergeSort(rightPart))
}
mergeSort(data)
return count % 1000000007
} function InversePairs(data)
{
// write code here
let sum = 0
mergeSort(data)
return sum
function mergeSort(nums){
if(nums.length<2) return nums
const mid = Math.floor(nums.length/2)
let left = nums.slice(0, mid)
let right = nums.slice(mid)
console.log(left, right)
return merge(mergeSort(left), mergeSort(right))
}
function merge(left, right){
let res = []
let lenL = left.length
let lenR = right.length
let len = lenL + lenR
for(let index = 0, i = 0,j = 0;index<len;index++){//i为arrLL的数组下标,j为arrLR的数组下标, index为新数组res的下标,初始值都为0
if(i>=lenL) res[index] = right[j++]
else if(j>=lenR) res[index] = left[i++]
else if(left[i]<= right[j]) res[index] = left[i++]
else{
res[index] = right[j++]
sum =((lenL - i)+sum)%1000000007// 核心代码,mergeSort和merge皆为归并排序代码
}
}
console.log(res)
return res
}
} 1. 二叉查找树版
function InversePairs(data) { if (data.length < 2) return 0; let mod = 1000000007; var ret = 0; function TreeNode(x) { this.val = x; this.left = null; this.right = null this.lkids = 0; this.rkids = 0; } function Insert(p, x) { let n = 0; while (true) { if (x > p.val) { p.rkids++; if (p.right) p = p.right; else { p.right = new TreeNode(x); break; } } else { p.lkids++; n += p.rkids + 1; if (p.left) p = p.left; else { p.left = new TreeNode(x); break; } } } ret += n; if (ret >= mod) ret -= mod; } let r = new TreeNode(data[0]); for (let i = 1; i < data.length; i++) { Insert(r, data[i]); } return ret; }2. 树状数组版
function InversePairs(data) { if (data.length < 2) return 0; var ret = 0; let mod = 1000000007; let bit = new Array(2000002).fill(0); function add(i, d) { while (i < bit.length) { bit[i] += d; i += i & -i; } } function sum(x) { let sum = 0; while (x > 0) { sum += bit[x]; x -= x & -x; } return sum; } for (let i = 0; i < data.length; i++) { ret += i - sum(data[i] + 1); add(data[i] + 1, 1); } return ret % mod; }
/* 这个超时了,我也不知道是为什么,思路是一样的,都是分治的思想
function InversePairs(data) {
// write code here
/**
* 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总
* 数P。并将P对1000000007取模的结果输出。 即输出P%1000000007
*
* 借用分治的的思想,先两两等分,对每一份统计逆序对的数量,并进行排序,排序之后进行合并,边合并边统计逆序对的数量
if (!data || data.length < 2) {
return 0
}
let count = 0
const mergeArr = (arr, first, mid, end) => {
//传入的mid是取不到的,前半段为first~mid-1,后半段为mid~end-1
// 将数组的一段进行合并排序
let temp = [] // 临时数组,用于保存end-first排序之后的序列
let i = 1, j = 1
while (i <= mid - first && j <= end - mid) {
if (arr[mid - i] > arr[end - j]) {
temp.unshift(arr[mid - i])
count += (end - j - mid + 1)
i++
} else {
//此时说明前面的数小于后面的数,未形成逆序对
temp.unshift(arr[end - j])
j++
}
}
while (i <= mid - first) {
temp.unshift(arr[mid - i])
i++
}
while (j <= end - mid) {
temp.unshift(arr[end - j])
j++
}
//console.log(temp)
arr.splice(first, end - first, ...temp)
}
function mergeSort(arr, first, end) {
//递归进行归并排序
let mid = (first + end) >> 1
if (first < mid) {
mergeSort(arr, first, mid)
mergeSort(arr, mid, end)
mergeArr(arr, first, mid, end)
//console.log(arr)
}
}
mergeSort(data, 0, data.length)
//console.log(count)
return count % 1000000007
}
//InversePairs([2,5,1,4,6,8,3,7])
module.exports = {
InversePairs : InversePairs
};
*/
function InversePairs(data)
{
var copy = data.slice();
return mergeInversePairs(data, copy, 0, data.length - 1) % 1000000007;
}
function mergeInversePairs(arr, copy, begin, end) {
if(begin === end) {
return 0;
}
var mid = begin + end >> 1;
var left = mergeInversePairs(arr, copy, begin, mid);
var right = mergeInversePairs(arr, copy, mid + 1, end);
var num = 0, i = mid, j = end, k = end;
while(i >= begin && j >= mid + 1) {
if(arr[i] <= arr[j]) {
copy[k--] = arr[j--];
} else {
num += j - mid;
copy[k--] = arr[i--];
}
}
while(i >= begin) copy[k--] = arr[i--];
while(j >= mid + 1) copy[k--] = arr[j--];
for(var s = begin; s <= end; s++)
{
arr[s] = copy[s];
}
return num + left + right;
}
module.exports = {
InversePairs : InversePairs
};
function InversePairs(data)
{
if(!data||data.length<2) return 0;
let copy=data.slice(),count=0;
count=mergeCount(data,copy,0,data.length-1);
return count%1000000007;
}
function mergeCount(data,copy,start,end){
if(start==end) return 0;
let mid=(end-start)>>1,
left=mergeCount(copy,data,start,start+mid),//注意参数,copy作为data传入
right=mergeCount(copy,data,start+mid+1,end),//注意参数,copy作为data传入 [p,q,count,copyIndex]=[start+mid,end,0,end];
while(p>=start&&q>=start+mid+1){
if(data[p]>data[q]){
copy[copyIndex--]=data[p--];
count=count+q-start-mid;
}else{
copy[copyIndex--]=data[q--];
}
}
while(p>=start){
copy[copyIndex--]=data[p--];
}
while(q>=start+mid+1){
copy[copyIndex--]=data[q--];
}
return count+left+right;
}
function InversePairs(data) {
// write code here
var sortedArray = getSorted(data);
return sortedArray.count;
}
function getSorted(data) {
var length = data.length;
if (length <= 1) return data;
var mid = Math.floor(length / 2),
left = data.slice(0, mid),
right = data.slice(mid, length);
return merge(getSorted(left), getSorted(right));
}
function merge(left, right) {
var li = left.length - 1,
ri = right.length - 1;
var ansArray = [];
var count = (left.count ? left.count : 0) + (right.count ? right.count : 0);
for (; li >= 0 && ri >= 0;) {
if (left[li] > right[ri]) {
count += ri + 1;
if (count > 1000000007) count = count % 1000000007;
ansArray.unshift(left[li]);
li--;
} else {
ansArray.unshift(right[ri]);
ri--;
}
}
while (li >= 0) {
ansArray.unshift(left[li--]);
}
while (ri >= 0) {
ansArray.unshift(right[ri--]);
}
ansArray['count'] = count % 1000000007;
return ansArray;
}
//超时............