在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。 即输出P mod 1000000007
数据范围: 对于 的数据,
对于 的数据,
数组中所有数字的值满足
要求:空间复杂度 ,时间复杂度
题目保证输入的数组中没有的相同的数字
[1,2,3,4,5,6,7,0]
7
[1,2,3]
0
class Solution { public: int InversePairs(vector<int> data) { int length=data.size(); if(length<=0) return 0; //vector<int> copy=new vector<int>[length]; vector<int> copy; for(int i=0;i<length;i++) copy.push_back(data[i]); long long count=InversePairsCore(data,copy,0,length-1); //delete[]copy; return count%1000000007; } long long InversePairsCore(vector<int> &data,vector<int> ©,int start,int end) { if(start==end) { copy[start]=data[start]; return 0; } int length=(end-start)/2; long long left=InversePairsCore(copy,data,start,start+length); long long right=InversePairsCore(copy,data,start+length+1,end); int i=start+length; int j=end; int indexcopy=end; long long count=0; while(i>=start&&j>=start+length+1) { if(data[i]>data[j]) { copy[indexcopy--]=data[i--]; count=count+j-start-length; //count=count+j-(start+length+1)+1; } else { copy[indexcopy--]=data[j--]; } } for(;i>=start;i--) copy[indexcopy--]=data[i]; for(;j>=start+length+1;j--) copy[indexcopy--]=data[j]; return left+right+count; } };
归并排序思想
时间复杂度:O(nlogn) 空间复杂度:O(n)
class Solution: sum_ = 0 def merge_sort(self, data): n = len(data) if n <= 1: return data mid = n // 2 left = self.merge_sort(data[:mid]) right = self.merge_sort(data[mid:]) l, r = 0, 0 temp = [] while l < len(left) and r < len(right): if left[l] > right[r]: self.sum_ += len(left) - l temp.append(right[r]) r += 1 else: temp.append(left[l]) l += 1 temp += left[l:] temp += right[r:] return temp def InversePairs(self , data: List[int]) -> int: self.merge_sort(data) return self.sum_ % 1000000007
import java.util.Arrays; public class Solution { static int reslut = 0; public static int InversePairs(int[] array) { sort(array, 0, array.length - 1); return reslut; } static void sort(int[] array, int l, int r) { if (l >= r) return; int mid = (l + r) / 2; sort(array, l, mid); sort(array, mid + 1, r); if (array[mid] > array[mid + 1]) { reslut += merge(array, l, mid, r); if(reslut>1000000007) reslut-=1000000007; } } static int merge(int[] array, int l, int mid, int r) { int tc = 0; int c = 0; int[] temp = Arrays.copyOfRange(array, l, r + 1); int i = l, j = mid + 1; for (int k = l; k <= r; k++) { if (i > mid) { array[k] = temp[j - l]; j++; } else if (j > r) { array[k] = temp[i - l]; c += tc; tc = 0; i++; } else if (temp[i - l] < temp[j - l]) { array[k] = temp[i - l]; c += tc; tc = 0; i++; } else { array[k] = temp[j - l]; tc += mid - i + 1; j++; } } return c; } }
//思路:分治的思想。 //在合并有序数组时,当左边数组的指针移动至下一元素时,说明该指针的元素能够和右指针元素之前的所有元素构成逆序对关系。 //所以逆序对总数加上右边指针前的元素个数。 //https://leetcode-cn.com/problems/shu-zu-zhong-de-ni-xu-dui-lcof/solution/shu-zu-zhong-de-ni-xu-dui-by-leetcode-solution/ class Solution{ private: int merge_sort(vector<int>& nums, int l, int r, vector<int>& tmp){ //易错点:按引用传递,经常忘写&号,然后错误极为隐蔽,经常半天找不到错误。(堪比==写成=) if(l >= r - 1) return 0; long long count = 0; //注意这里用int的话,结果会因为溢出而输出负数 //分 int m = (l + r) / 2; count += merge_sort(nums, l, m, tmp); count += merge_sort(nums, m, r, tmp); //治 int p = l, q = m, k = l; //使用双指针合并有序数组 while(p < m || q < r){ if(q >= r || p < m && nums[p] <= nums[q]){ count += (q - m); tmp[k++] = nums[p++]; } else tmp[k++] = nums[q++]; } for(int k = l; k<r; k++){ nums[k] = tmp[k]; } return (count % 1000000007); } public: int InversePairs(vector<int> data){ vector<int> tmp(data.size()); return merge_sort(data, 0, data.size(), tmp) ; } };
class Solution { public: #define ll long long #define mod 1000000007 #define N 100010 int lowbit(int i){ return i&(-i); } void add(int i,int x){ while(i<=n){ c[i]+=x; i+=lowbit(i); } return ; } int getsum(int i){ int sum=0; while(i>0){ sum+=c[i]; i-=lowbit(i); } return sum; } int InversePairs(vector<int> data) { n=data.size(); vector<pair<int,int> >da; for(int i=0;i<n;i++){ da.push_back(make_pair(data[i],i+1)); } sort(da.begin(),da.end()); for(int i=0;i<n;i++){ hash[da[i].second]=i+1; } ll ans=0; for(int i=1;i<=n;i++){ add(hash[i],1); ans+=(ll)i-getsum(hash[i]); ans%=mod; } return ans; } private: int c[N]; int hash[N]; int n; };
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 }
void add(int* tree, int k, int n) { while(k<=n) { tree[k] += 1; k += k&(-k); } } long long sum_tree(int* tree, int k) { long long ans = 0; while(k) { ans += tree[k]; k -= k&(-k); } return ans; } class Solution { public: int InversePairs(vector<int> data) { int n = data.size(); vector<int> a = data; sort(a.begin(), a.end()); int cnt = 0; for(int i=1; i<n; i++) if(a[i] != a[cnt]) a[++cnt] = a[i]; int tree[cnt+7]; memset(tree, 0, sizeof(tree)); long long ans = 0; for(int i=0; i<n; i++) { int id = lower_bound(a.begin(),a.end(), data[i]) - a.begin() + 1; ans = (ans + sum_tree(tree, cnt+1) - sum_tree(tree, id)) % mod; add(tree, id, cnt+1); } return ans; } const long long mod = 1e9 + 7; };
class Solution { public: int InversePairs(vector<int> data) { return merge(data,0,data.size()-1); } int merge(vector<int>& data, int left,int right) { if(left==right) { return 0; //只有一个数,不存在逆序对 } vector<int> tem; int mid=left+((right-left)>>1); long long x=merge(data,left,mid); x+=merge(data,mid+1,right); int i=left,j=mid+1; while(i<=mid && j<=right) { if(data[i]>data[j]) { x+=(mid-i+1); //逆序对 tem.push_back(data[j++]); } else{ tem.push_back(data[i++]); } } while(i<=mid) { tem.push_back(data[i++]); } while(j<=right) { tem.push_back(data[j++]); } // copy(data.begin()+mid+1,data.begin()+right+1,tem); for(int i=left;i<=right;i++) { data[i]=tem[i-left]; } return x%1000000007; } };
# -*- coding:utf-8 -*- class Solution: #用来定义一个count,就可以不断的在原来基础上叠加了 def __init__(self): self.count = 0 def InversePairs(self, data): # write code here #这个是用来合的函数,返回res,只是在合的过程中可以用来计算count def merge(s1, s2): res = [] i = j = 0 n = len(s1) m = len(s2) while i < n and j < m: if s1[i] > s2[j]: self.count += n - i res.append(s2[j]) j += 1 else: res.append(s1[i]) i += 1 res += s1[i:] if i < n else s2[j:] return res #这个是用来分的函数,就是一直分分分,直到列表中只剩下1个 def merge_sort(li): if len(li) == 1: return li if len(li)<1: return [] mid = len(li)//2 lt = merge_sort(li[:mid]) rt = merge_sort(li[mid:]) return merge(lt, rt) #就是用来merge后看看count多少,最后返回一下就行了 if len(data) < 2: return 0 merge_sort(data) return self.count%1000000007分治法,归并排序,好处是比较一下就可以输出好多不重复的答案
class Solution { public: void copy(vector<int> &dst, vector<int> &src, int l, int r) { while (l <= r) { dst[l] = src[l]; l++; } } long merge(vector<int> &data, vector<int> &tmp, int l, int m, int r) { int i = l, j = m + 1, k = l; long ret = 0; while (i <= m && j <= r) { if (data[i] <= data[j]) { tmp[k++] = data[i++]; } else { tmp[k++] = data[j++]; ret += (m - i + 1); } } while (i <= m) { tmp[k++] = data[i++]; } while (j <= r) { tmp[k++] = data[j++]; } return ret; } long mergesort(vector<int> &data, vector<int> &tmp, int l, int r) { long left = 0, right = 0, cnt = 0; if (l < r) { int m = (l + r) / 2; left = mergesort(data, tmp, l, m) % 1000000007; right = mergesort(data, tmp, m+1, r) % 1000000007; cnt = merge(data, tmp, l, m, r) % 1000000007; copy(data, tmp, l, r); } return (left + right + cnt) % 1000000007; } int InversePairs(vector<int> data) { vector<int> tmp(data.size()); return mergesort(data, tmp, 0, data.size()-1); } };
import java.util.Arrays; public class Solution { // 采用归并排序 public int InversePairs(int[] array){ int len = array.length; if(array == null || len == 0) return 0; int[] copy = array.clone(); return InversePairs(copy, 0, len - 1); } public int InversePairs(int[] copy, int begin, int end){ if(begin == end) return 0; int mid = (begin + end) >> 1; int leftCnt = InversePairs(copy, begin, mid) % 1000000007; int rightCnt = InversePairs(copy, mid + 1, end) % 1000000007; int cnt = 0; int i = mid; int j = end; while(i >= begin && j > mid){ if(copy[i] > copy[j]){ cnt += (j - mid); if(cnt >= 1000000007) cnt = cnt % 1000000007; i--; }else j--; } Arrays.sort(copy, begin, end + 1); return (leftCnt + rightCnt + cnt) % 1000000007; } }
class Solution { public: long long num=0;//逆序次数 //归并操作,一边归并,一边统计逆序次数 //归并 [left,mid]和(mid,right] int InversePairs(vector<int> data) { //使用归并排序的思想 vector<int> temp(data.size());//创建一个临时数组,只用创建一次,避免多次创建 sort(data,0,data.size()-1,temp); return num%=1000000007; } //归并排序 void sort(vector<int>& data,int left,int right,vector<int>& temp) { if(left<right) { int mid=left+((right-left)>>1); sort(data,left,mid,temp); sort(data,mid+1,right,temp); mergeVec(data,left,mid,right, temp); } } //归并操作 void mergeVec(vector<int>& data,int left,int mid,int right,vector<int>& temp ) { int l1=left; int l2=mid+1; int index=left; while(l1<=mid&&l2<=right) { if(data[l1]<=data[l2]) temp[index++]=data[l1++]; else//逆序了 { temp[index++]=data[l2++]; //下面这两行是相对于归并排序增加的两行,如果只是归并排序,不要下面这两行就可以了 num+=mid-l1+1;//data[l1]一直到data[mid]都大于data[l2],就存在mid-l1+1对逆序对 num%=1000000007; } } while(l1<=mid) temp[index++]=data[l1++]; while(l2<=right) temp[index++]=data[l2++]; for(int i=left;i<=right;i++) data[i]=temp[i]; } };
class Solution { public: int count=0; void Merge(vector<int> &data,int l,int m,int r) { vector<int> temp; int i=l; int j=m+1; while(i<=m && j<=r) { if(data[i]>data[j]) { count=count+m-i+1; temp.push_back(data[j++]); } else { temp.push_back(data[i++]); } } while(i<=m) { temp.push_back(data[i++]); } while(j<=r) { temp.push_back(data[j++]); } for(int i=0;i<temp.size();++i) { data[i+l]=temp[i]; } } void Merge_sort(vector<int> &data,int l,int r) { if(l<r) { int m=(r-l)/2+l; Merge_sort(data,l,m); Merge_sort(data,m+1,r); Merge(data,l,m,r); } } int InversePairs(vector<int> data) { if(!data.size()) { return 0; } Merge_sort(data,0,data.size()-1); return (count%1000000007); } };归并排序,分治成单个子序列,再归并排序的同时统计逆序对。
public class Solution { private static long sum = 0; public int InversePairs(int [] array) { int len = array.length; int l = 0; int r = len - 1; divide(l, r, array); return (int) (sum % 1000000007); } private void divide(int l, int r, int[] array) { if (l == r) return; if (l != r) { int mid = (l + r) >> 1; divide(l, mid, array); divide(mid + 1, r, array); merge(l, mid, r, array); } } private void merge(int l, int mid, int r, int[] array) { int i = l;//左区间起点 int j = mid + 1;//右区间起点 int[] temp = new int[r - l + 1]; int idx = 0; while (i <= mid && j <= r) { if (array[i] > array[j]) { sum += mid - i + 1;//更新逆序对数量 temp[idx] = array[j]; ++idx; ++j; } else { temp[idx] = array[i]; ++idx; ++i; } } while (i <= mid) { temp[idx] = array[i]; ++idx; ++i; } while (j <= r) { temp[idx] = array[j]; ++idx; ++j; } idx = 0; for (int k = l; k <= r; k++) { array[k] = temp[idx]; ++idx; } } }
public class Solution { int th;//利用归并排序 O(o*logn) public int InversePairs(int [] array) { mergeSort(array,0,array.length-1); return th; } public 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); } public 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++]; th=(th+(mid-i+1))%1000000007;////如果前面的元素大于后面的,那么在前面元素之后的元素都能和后面的元素构成逆序对 } } while(i<=mid) tmp[k++] = array[i++]; while(j<=end) tmp[k++] = array[j++]; for(int l=0;l<k;l++){ array[start+l]=tmp[l]; } } }