数组中的逆序对python_数组中的逆序对

11

import java.util.*;

//这个题和上一个求数组的秩是类似的,逆序对=当前数组长度 - 秩,

//在秩的基础上,把左右子树对调一下就可以了,在秩的基础上修改两个不等号就ok了

public class AntiOrder {

Node root = null;

public int count(int[] A, int n) {

int res = 0;

for (int i = 0; i < n; i++) {

res += helper(A[i]);

}

return res;

}

public int helper(int a) {

if (root == null) {

root = new Node(a);

return 0;

} else {

root.insert(a);

return root.getRank(a);

}

}

}

class Node {

int leftSize = 0;

Node left, right;

int val;

public Node(int v) {

val = v;

}

public void insert(int v) {

if (v > val) {

if (left != null)

left.insert(v);

else

left = new Node(v);

leftSize++;

} else {

if (right != null)

right.insert(v);

else

right = new Node(v);

}

}

public int getRank(int v) {

if (v == val)

return leftSize;

if (v > val)

return left.getRank(v);

if (v < val)

return leftSize + 1 + right.getRank(v);

return 0;

}

}

发表于 2015-09-10 15:32:38

回复(0)

4

/*

[1,2,3,4,5,6,7,0],8

7

类似11.8,也可以用multiset(底层为红黑树)做,

以0为例,end-cur即为0的逆序对数目

*/

class AntiOrder {

public:

int count(vector A, int n) {

// write code here

int ret = 0;

multiset mset;

multiset::iterator cur, end;

for (int i = 0; i < n; i++)

{

mset.insert(A[i]);

cur = mset.upper_bound(A[i]);

end = mset.end();

while (cur != end)

{

ret++;

cur++;

}

}

return ret;

}

};

发表于 2017-02-21 10:55:15

回复(0)

4

int merge(int[] A, int start, int mid, int end) {

int[] aux = new int[end - start + 1];

int i = start;

int j = mid + 1;

int k = 0;

int reverse = 0;

while (i <= mid && j <= end) {

if (A[i] <= A[j]) {

aux[k++] = A[i++];

} else {

reverse += mid - i + 1;

aux[k++] = A[j++];

}

}

while (i <= mid) {

aux[k++] = A[i++];

}

while (j <= end) {

aux[k++] = A[j++];

}

for (int m = 0; m < aux.length; ++m) {

A[start + m] = aux[m];

}

returnreverse;

}

public int count(int[] A, int start, int end) {

if (end <= start) {

return 0;

}

int mid = (start + end) >> 1;

int count1 = count(A, start, mid);

int count2 = count(A, mid + 1, end);

returncount1+count2+ merge(A,start,mid,end);

}

public int count(int[] A, int n) {

// write code here

return count(A, 0, n - 1);

}

发表于 2016-04-27 20:50:17

回复(0)

6

利用归并排序,在对有序子数组进行merge的同时,累加逆序对,时间复杂度O(nlogn)

编辑于 2017-07-28 15:08:55

回复(2)

9

/*

冒泡排序时做了多少次交换就有多少个逆序

*/

class AntiOrder {

public:

int count(vector A, int n) {

// write code here

int count = 0;

int i,j;

if(n < 2) return n;

for(i=0;i

for(j=0;j

if(A[j]>A[j+1]){

swap(A[j],A[j+1]);

count++;

}

}

}

return count;

}

};

发表于 2015-09-06 19:07:43

回复(2)

5

import java.util.*;

public class AntiOrder {

public int count(int[] A, int n) {

int sum=0;

for(int i=0;i

for(int j=i+1;j

if(A[i]>A[j])

sum++;

}

return sum;

}

}

发表于 2018-09-16 22:19:35

回复(0)

1

class AntiOrder {

public:

//归并排序,前面一块数据中没出现一个值比后面值的数,则前面之后的数都比后面的该数大

void merge_sort(vector& A,int start,int end,vector& tmp,int& count)

{

if(start == end)

return;

int mid = (start+end)/2;

merge_sort(A,start,mid,tmp,count);

merge_sort(A,mid+1,end,tmp,count);

int i=start,j=mid+1;

int ind = start;

while(i<=mid && j<=end)

{

if(A[i] > A[j])

{

count += mid-i+1;

tmp[ind++] = A[j++];

}else

{

tmp[ind++] = A[i++];

}

}

while(i <= mid)

{

tmp[ind++] = A[i++];

}

while(j <= end)

{

tmp[ind++] = A[j++];

}

for(int k=start;k<=end;++k)

{

A[k] = tmp[k];

}

}

int count(vector A, int n) {

// write code here

vector tmp(n,0);

int num = 0;

merge_sort(A,0,n-1,tmp,num);

return num;

}

};

发表于 2020-07-21 23:25:17

回复(0)

1

class AntiOrder {

public:

int count(vector A, int n) {

multiset s;

int cnt = 0;

for(int i=0;i

s.insert(A[i]);

multiset::iterator p = s.upper_bound(A[i]);

while(p!=s.end()){

p++;

cnt++; } } return cnt;

}

};

发表于 2019-03-09 01:51:01

回复(0)

1

import java.util.*;

//其实也就是求一个数左边有少个比它大的,排序后p2之前的数就是p2的所有逆序对 (R-p2+1)

public class AntiOrder {

public int count(int[] A,int n) {

if(A == null || n == 0) return 0;

return mergSort(A,0,A.length-1);

}

public int mergSort(int[] arr,int L,int R){

if(L == R) return 0;

int mid = L+ ((R-L) >> 1);

return mergSort(arr,L,mid)+mergSort(arr,mid+1,R)+merg(arr,L,mid,R);

}

public int merg(int[] arr,int L,int mid,int R){

int[] help = new int[R-L+1];

int i = 0;

int count = 0;

int p1 = L;

int p2 = mid+1;

while(p1 <= mid && p2 <= R){

if(arr[p1] > arr[p2]){

count += (R-p2)+1;

help[i++] = arr[p1++];

}else{

help[i++] = arr[p2++];

}

}

while(p1 <= mid){

help[i++] = arr[p1++];

}

while(p2 <= R){

help[i++] = arr[p2++];

}

for (int j = 0; j < help.length; j++) {

arr[L + j] = help[j];

}

return count;

}

}

发表于 2019-01-22 20:02:11

回复(0)

1

//遍历数组,如果前面的值比后面的值大,就是一个逆序对。时间复杂度O(n*n).

//O(nlogn)的算法是采用归并排序。

class AntiOrder {

public:

int count(vector A, int n) {

int count = 0;

for(int i = 0;i < n-1;++i)

{

for(int j = i;j < n;++j)

{

if(A[i] > A[j])

count++;

}

}

return count;

}

};

编辑于 2018-08-28 11:46:17

回复(0)

1

import java.util.*;

/*

错误的思路:先排序,再对比排序后的数字和排序前的数字位置,相同数字在不同位置之间的位置差的数目就是逆序对的数目

如何找相同数字的不同位置~用二分法可以降复杂度,时间复杂度O(nlogn)

很想知道我这个思路哪里错了啊!!!求大神解释

正确的思路:归并排序

*/

/*

public class AntiOrder {

public int count(int[] A, int n) {

int b[] =new int[n];

int j=0;

int sum=0;

for(int m:A){

b[j]=m;

j++;

}

Arrays.sort(b);

for(j=0;j

int start=0;

int end =n-1;

int mid=0;

while(start<=end){

mid =(start+end)/2;

if(A[j]==b[mid]) break;

else if(A[j]>b[mid]) start=mid+1;

else end =mid-1;

}

if(mid-j>0) sum=sum+mid-j;

}

return sum;

}

}

*/

public class AntiOrder {

public int count(int[] A, int n) {

if(A==null||A.length==0) return 0;

int []copy=new int[n];

for(int i=0;i

copy[i]=A[i];

}

return mergesort(A,copy,0,n-1);

}

public int mergesort(int[] A,int[] copy,int start,int end){

if(start==end){

copy[start] =A[start];

return 0;

}

int mid=(start+end)/2;

int left =mergesort(copy,A,start,mid);

//这里要注意了,copy和A的数组互换了,实际上我们比较的都是copy中的数组值,而不是A的数组值

//因为copy中数组是一直保持分段数组内部顺序的(即每次逆序对计算完,都会把计算完的逆序对顺序调整)

//用copy数组比较才不会出现重复计算逆序对的情况,这里如果不互换顺序会多计算无数次逆序对

int right =mergesort(copy,A,mid+1,end);

int i=mid,j=end,count=0,index=end;

while(i>=start&&j>mid){

if(A[i]>A[j]){

count +=j-mid;

copy[index--]=A[i--];

}else{

copy[index--]=A[j--];

}

}

while(i>=start){

copy[index--]=A[i--];

}

while(j>mid){

copy[index--]=A[j--];

}

return count+left+right;

}

}

运行时间:205ms

占用内存:13612k

发表于 2017-07-05 17:17:56

回复(0)

1

归并排序

class AntiOrder {

public:

int mergeSort(vector& A, vector& temp, int left, int right)

{

if (left >= right) return 0;

int reverseCount = 0;

int mid = (left + right) >> 1;

reverseCount += mergeSort(A, temp, left, mid);

reverseCount += mergeSort(A, temp, mid + 1, right);

int pos, i, j;

for (pos = left,i = left, j = mid + 1; j <= right; ++j)

{

while (i <= mid && A[i] < A[j])

{

temp[pos] = A[i];

++pos;

++i;

}

if (i <= mid) reverseCount += mid - i + 1;

temp[pos] = A[j];

++pos;

}

while (i <= mid) temp[pos++] = A[i++];

memcpy(A.data() + left, temp.data() + left, (right - left + 1) * sizeof(int));

return reverseCount;

}

int count(vector A, int n)

{

vector temp(n, 0);

return mergeSort(A, temp, 0, n - 1);

}

};

发表于 2017-06-30 14:46:22

回复(0)

1

class AntiOrder:

def count(self, A, n):

self.rNums = 0

self.mergeSort(A)

return self.rNums

def mergeSort(self, A):

if len(A) <= 1:

return A

m = len(A) / 2

a = self.mergeSort(A[:m])

b = self.mergeSort(A[m:])

return self.merge(a, b)

def merge(self, A, B):

c, i, j = [], 0, 0

while i < len(A) and j < len(B):

if A[i] <= B[j]:

c.append(A[i])

i += 1

else:

c.append(B[j])

j += 1

self.rNums += len(A) - i #此为逆序对数

c += A[i:]

c += B[j:]

return c

发表于 2017-03-05 13:53:15

回复(0)

1

class AntiOrder {

public:

int count(vector data, int n) {

// write code here

if(data.size()<=1) return 0;

int* copy=new int[data.size()];

//初始化数组

for(unsigned int i=0;i

copy[i]=0;

int count=InversePairCore(data,copy,0,data.size()-1);

delete[] copy;

return count;

}

int InversePairCore(vector& data,int*& copy,int start,int end)

{

if(start==end)

{

copy[start]=data[start];

return 0;

}

//将数组拆分成两部分

int length=(end-start)/2;

//分别计算左边部分和右边部分

int left=InversePairCore(data,copy,start,start+length)%1000000007;

int right=InversePairCore(data,copy,start+length+1,end)%1000000007;

//进行逆序计算

int i=start+length;

int j=end;

int index=end;

int count=0;

while(i>=start && j>=start+length+1)

{

if(data[i]>data[j])

{

copy[index--]=data[i--];

//统计长度

count+=j-start-length;

if(count>=1000000007)//数值过大求余

count%=1000000007;

}

else

{

copy[index--]=data[j--];

}

}

for(;i>=start;--i)

{

copy[index--]=data[i];

}

for(;j>=start+length+1;--j)

{

copy[index--]=data[j];

}

//排序

for(int i=start; i<=end; i++) {

data[i] = copy[i];

}

//返回最终的结果

return (count+left+right)%1000000007;

}

};

发表于 2016-08-14 17:32:58

回复(0)

1

/*

* 数组的逆序对就是当前数组长度-秩,与上题一样,维护一组二叉查找树,每次添加新值后得到该数组对应的秩,用当前数组长度-秩

* 对所有值的添加过程都进行逆序对计算,并加和即可

*/

public class RankNode{

public int left_size = 0;

public RankNode left, right;

public int data = 0;

public RankNode(int d) {

// TODO Auto-generated constructor stub

data = d;

}

public void insert(int d) {

// TODO Auto-generated method stub

if(d <= data){

if(left != null){

left.insert(d);

}else{

left = new RankNode(d);

}

left_size++;

}else{

if(right != null){

right.insert(d);

}else{

right = new RankNode(d);

}

}

}

public int getRank(int d) {

// TODO Auto-generated method stub

if(d == data){

return left_size;

}else if(d < data){

if(left == null){

return -1;

}else{

return left.getRank(d);

}

}else{

int right_rank = right == null ? -1 : right.getRank(d);

if(right_rank == -1) return -1;

return left_size + 1 + right.getRank(d);

}

}

}

public int count(int[] A, int n) {

// write code here

if(A == null || A.length != n || n <= 0){

return 0;

}

RankNode root = new RankNode(A[0]);

int[] ranks = new int[n];

int res = 0;

for(int i = 1; i < n; i++){

root.insert(A[i]);

ranks[i] = root.getRank(A[i]);

res += i - ranks[i];

}

return res;

}

发表于 2016-06-11 23:32:44

回复(0)

1

Solution: 提供两种解决方案:

Method 1: brute force O(n^2)

Method 2: merge sort O(nlogn)

//Method 2: merge sort

发表于 2016-01-02 15:46:13

回复(0)

1

大概思路是归并排序的思想,先分为2个左右部分,左部分的逆序对(只在左部分取2个数),右部分的逆序对(只在右部分取2个数),满足在左部分取一个数,右部分取一个数的逆序对,以上全部加起来就是总的逆序对。计算左右部分的逆序对的时候,利用递归。

class Solution {

public:

int InversePairs(vector data) {

return merge(data, 0, data.size() - 1);

}

int merge_count(vector &data, int start, int mid, int end)//计算满足左部分一个数,右部分一个数条件的逆序对,此时左右部分已排好序

{

vector temp(data);

int count = 0;

int i = start;

int j = mid + 1;

int k = start;

while (i <= mid&&j <= end)

{

if (data[i] <=data[j])

temp[k++] = data[i++];

else

{

temp[k++] = data[j++];

count = count + mid- i+1;

}

}

while (i <= mid)temp[k++] = data[i++];

while (j <= end)temp[k++] = data[j++];

for (int m = start; m <= end; m++)

data[m] = temp[m];

return count;

}

int merge(vector &data, int start, int end)//左右部分分别递归,

{

if (start >= end)

return 0;

int mid = (start + end) / 2;

int left=merge(data, start, mid);

int right=merge(data, mid + 1, end);

int count = merge_count(data, start, mid, end);

return left + right + count;

}

};

发表于 2015-11-04 10:04:32

回复(0)

1

//常规思想,找出每个元素的逆序对,复杂度是O(N*N)

//利用归并排序的思想,先划分再合并,复杂度可以降到O(NlogN)

class AntiOrder {

public:

void merge(vector &v,int a1,int a2,int b1,int b2,int &pairs){

vector tmp;

int i=a1;

int j=b1;

while(i<=a2&&j<=b2){

if(v[i]<=v[j]){

tmp.push_back(v[i++]);

pairs=pairs+j-b1;

}

else{

tmp.push_back(v[j++]);

}

}

while(i<=a2){

tmp.push_back(v[i++]);

pairs=pairs+b2-b1+1;

}

while(j<=b2) tmp.push_back(v[j++]);

for(i=0,j=a1;j<=b2;j++)

v[j]=tmp[i++];

}

void fun(vector &v,int p1,int p2,int &pairs){

if(p1==p2)

return;

fun(v,p1,(p1+p2)/2,pairs);

fun(v,(p1+p2)/2+1,p2,pairs);

merge(v,p1,(p1+p2)/2,(p1+p2)/2+1,p2,pairs);

}

int count(vector A, int n) {

int pairs=0;

fun(A,0,n-1,pairs) ;

return pairs;

}

};

编辑于 2015-10-19 21:07:34

回复(0)

0

# -*- coding:utf-8 -*-

class AntiOrder:

def count(self, A, n):

# write code here

self.res = 0

# 调用归并排序计算逆序数

self.mergeSort(A)

return self.res

def mergeSort(self, A):

if len(A) <= 1:

return A     # 递归结束

mid = len(A) // 2

left = self.mergeSort(A[:mid])    # 左边排好序

right = self.mergeSort(A[mid:])    # 右边排好序

merged = []

while left and right:

if left[0] <= right[0]:

merged.append(left.pop(0))

else:

self.res += len(left)    # 逆序数

merged.append(right.pop(0))

# 剩余部分放在数组后面

merged.extend(right if right else left)

return merged

发表于 2020-12-13 13:25:33

回复(0)

0

import java.util.*;

public class AntiOrder {

public int count(int[] A, int n) {

int num = 0;

for (int i = 0; i 

for (int j = i + 1; j 

if(A[i] > A[j]) {

num++;

}

}

}

return num;

}

}

发表于 2020-03-31 23:40:00

回复(0)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值