在數組中的兩個數字,若是前面一個數字大於後面的數字,則這兩個數字組成一個逆序對。輸入一個數組,求出這個數組中的逆序對的總數。算法
很容易想到從後往前折半插入排序時順便記錄比當前數小得數,可是這種方法在用例30的時候就超時了。。數組
class Solution { public: int count(vector<int>& nums, int pivot, int st, int ed){ int l=st,r=ed; if(nums[pivot]<=nums[st])return 0; if(nums[pivot]>nums[ed]){ int tmp=nums[pivot]; for(int i=st;i<=ed;i++){ nums[i-1]=nums[i]; } nums[ed]=tmp; return ed-st+1; } while(l<r){ int mid=l+(r-l)/2; if(nums[mid]>=nums[pivot]) r=mid; else l=mid+1; } int tmp=nums[pivot]; for(int i=st;i<l;i++){ nums[i-1]=nums[i]; } nums[l-1]=tmp; return l-st; } int reversePairs(vector<int>& nums) { //從後往前折半插入排序 int n=nums.size(); int res=0; for(int i=n-2;i>=0;i--){ res+=count(nums,i,i+1,n-1); } return res; } };
而後我就思考畢竟插入排序要移動數組元素,最後的整體時間複雜度是O(n^2),那麼找到一個插入和比較都是logn複雜度的算法不就能夠了嗎,那不就是歸併排序嗎!spa
固然,須要O(n)的額外空間,時間複雜度爲O(logn)code
class Solution { public: int res=0; void merge(vector<int>& nums, int left, int mid, int right){ vector<int> tmp(right-left+1,0); int l1=left,l2=mid+1,l3=0; while(l1<=mid&&l2<=right){ if(nums[l1]<=nums[l2]){ tmp[l3++]=nums[l1++]; res+=(l2-mid-1); } else tmp[l3++]=nums[l2++]; } while(l1<=mid){ tmp[l3++]=nums[l1++]; res+=(l2-mid-1); } while(l2<=right)tmp[l3++]=nums[l2++]; for(int i=left;i<=right;i++){ nums[i]=tmp[i-left]; } } void mergeSort(vector<int>& nums, int left, int right){ if(left<right){ int mid = left+(right-left)/2; mergeSort(nums,left,mid); mergeSort(nums,mid+1,right); merge(nums,left,mid,right); } } int reversePairs(vector<int>& nums) { //歸併排序 int n=nums.size(); mergeSort(nums,0,n-1); return res; } };