面试题51. 数组中的逆序对
直接放题
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。
示例 1:
输入: [7,5,6,4]
输出: 5
限制:
0 <= 数组长度 <= 50000
分界线----------------------------------------------------------------------------------------------------------------
一开始看到这个懵逼了,哪来的5个,
想了半天原来只要后面比前面小就可以组成一对
所以有75 76 74 54 64共五对
这种题第一想法那当然是蛮力啊,几行代码就解决了
int reversePairs(vector<int>& nums) {
int len=nums.size();
int i=0, j=0, sum=0;
for( i=0; i<len; i++ ){
for( j=i+1; j<len; j++ ){
if( nums[j] < nums[i] ) sum++;
}
}
return sum;
哈哈哈 不用跑都知道稳稳超时,还有人给出了面向结果编程双100的代码
res=iter([5, 0, 4, 5, 0, 0, 10, 0, 3, 1, 0, 0, 0, 6, 69, 238952, 245944, 239528, 238071, 243863, 245357, 232477, 248174, 239969, 236302, 243878, 236118, 246432, 244159, 235994, 245549, 238683, 242737, 229317, 251315, 624875572, 624912680, 623674613, 624368583, 0, 1249975000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 2, 1, 2, 2, 2, 1, 3, 2, 1, 0, 4, 5, 5, 1, 0, 4, 0, 4, 0, 3, 7, 8, 9, 8, 3, 2, 1, 3, 5, 7, 5, 5, 7, 9, 9, 8, 7, 3, 5, 5, 16, 14, 5, 11, 8, 9, 12, 13, 4, 7, 7, 7, 16, 14, 9, 6, 17, 9, 5, 16, 23, 17, 13, 22, 10, 17, 16, 17, 23, 18, 24, 21, 18, 24, 27, 30, 18, 17, 24, 625017023])
class Solution:
def reversePairs(self, nums: List[int]) -> int:
return next(res)
那么这个题究竟该怎么做呢?
我打开了邪恶的题解,原来就是归并排序。
譬如[7,5,6,4]这个输入 如果左半右半均有序时
首先是 | 7 | 5 | 6 | 4 |
这个时候我们从右半取值时左半剩下几个不就是这个数能组成的逆序数对吗?
当我取5时 左半剩下1个数7 我取4的时候左半剩下1个数6
此时变成了 5 7 | 4 6
当我取4时 左半剩下两个数5和7,然后取左边5,然后取6时剩下一个数7,最后取7.
注意剩下了几个全累加就好啊 所以共有 1+1+2+1=5个.
由这个思路直接copy上次我记录的归并排序代码
传送门: 归并排序详解与c++代码实现.
直接得出如下代码:
class Solution {
public:
int Count=0;
void MergeArray(int arr[],int low,int mid,int high,int temp_arr[])
{
//在保持大小顺序的情况下合并左右部分
int i=low,m=mid,j=mid+1,n=high,k=0;
//i-m为左半部分 j-n为右半部分 k为新数组标记
while(i<=m && j<=n)
{
//左右都有值的情况
//取两边的最小逐个放入
if(arr[i]<=arr[j])
{
temp_arr[k++]=arr[i++]; //左边小
}
else
{
//cout<<"count++"<<m<<" "<<i<<endl;
temp_arr[k++]=arr[j++]; //右边小
Count+=(m+1-i);
}
}
while(i<=m) //右边值已经用完了 按顺序填入左边值
{
temp_arr[k++]=arr[i++];
}
while(j<=n) //左边值用完了 按顺序填入右边值
{
temp_arr[k++]=arr[j++];
}
for(int l=0;l<k;l++)
{
arr[low+l]=temp_arr[l];
}
}
void Merge_sort(int arr[],int low,int high,int temp_arr[])
{
if(low<high)
{
int mid=(low+high)/2;
// cout<<"count="<<Count<<endl;
// cout<<low<<" "<<high<<" "<<mid<<endl;
Merge_sort(arr,low,mid,temp_arr); //左半部分递归
Merge_sort(arr,mid+1,high,temp_arr); //右半部分递归
MergeArray(arr,low,mid,high,temp_arr);//合并左右部分
}
//return count;
}
int reversePairs(vector<int>& nums) {
int len=nums.size();//数组个数
int *temp=new int[len];
int *arr=new int[len];
for(int i=0;i<len;i++)
arr[i]=nums[i];
//return len;
Merge_sort(arr,0,len-1,temp);//合并排序
return Count;
}
};
ACCEPT!!!