剑指offer---数组中的逆序对
题目描述
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。 即输出P%1000000007
输入描述:
题目保证输入的数组中没有的相同的数字 数据范围: 对于%50的数据,size<=10^4 对于%75的数据,size<=10^5 对于%100的数据,size<=2*10^5
示例:
输入: 1,2,3,4,5,6,7,0
输出: 7
解题思路: 该题数组的size<=2*10^5,那么使用两层for循环就会出现超时的情况 那么可以使用归并排序思想来实现: 因为每次归并的时候,左边和右边的数组都是有序数组, 若左边的数组中的数字大于右边的数字,那么左边从当前位置起,到左边数组结束的长度,都可以与右边的数字组成逆序对。
如:
左边为4,6 右边为3,7 那么当4和3比较时,(4,3),(6,3)都可以组成逆序对
下面的代码就是在归并排序的基础上加了一行统计逆序对的代码。
//数组中的逆序对 static long sum = 0;//这里需要注意为 long 类型 void mergeArray(vector<int> &v,int left,int mid,int right){ int i = left;//左边数组的左指针 int j = mid+1;//右边数组的左指针 int k = 0;//临时数组的下标 vector<int> temp(right-left+1); while(i <= mid && j <= right){ if(v[i] > v[j]){ //此时左边数组的数字大于右边数组的数字 //可以组成逆序对 sum += mid - i + 1; //统计逆序对 temp[k++] = v[j++]; }else{ temp[k++] = v[i++]; } } while(i <= mid){ temp[k++] = v[i++]; } while(j <= right){ temp[k++] = v[j++]; } for(int m = 0;m < temp.size();m++){ v[left+m] = temp[m]; } } void divide(vector<int> &v,int left,int right){ if(left < right){ int mid = left + (right-left) >> 1; divide(v,left,mid); divide(v,mid+1,right); mergeArray(v,left,mid,right); } } int InversePairs(vector<int> data){ if(data.empty()){ return 0; } divide(data,0,data.size()-1); return sum % 1000000007; }
其他的排序算法代码实现: