第五天刷题,嗯,深呼吸,要坚持呀!
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。
示例 1:
输入: [7,5,6,4]
输出: 5
限制:
0 <= 数组长度 <= 50000
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/shu-zu-zhong-de-ni-xu-dui-lcof
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题目描述很简单,但是我想了很久都没有思路,尝试着暴力解决,很不幸,超时了,估算一下暴力的复杂度
n
∗
(
n
+
1
)
/
2
n*(n+1)/2
n∗(n+1)/2。实在没有思路,所以我看了一下评论,提到了归并排序,ok,我立马明白了。但我觉得我本身对归并算法的本质仍然理解的不够深入。否则我不会失败于思路上。
归并算法:
//升序排序
sort(left, right)
{
center = (left+right)/2
nums[left:center] = sort(left, center)
nums[center+1, right] = sort(center+1, right)
nums[left:center] = merge(nums[left:center], nums[center+1:right])
}
merge(nums1, nums2) //有序数列的归并
{
i, pos1, pos2=0
while(pos<nums1.size && pos<nums2.size)
{
if(nums1[po1]>nums2[pos2])
tmp[i++] = nums2[pos2++]
else
tmp[i++] = nums1[pos1++]
}
while(pos<nums1)
{}
while(pos<nums2)
{}
}
很棒,这是有一个归并算法的伪代码,它的复杂度是
n
∗
l
o
g
2
(
n
)
n*log_{2}(n)
n∗log2(n)
*图片来源:https://www.cnblogs.com/chengxiao/p/6194356.html
*
归并排序的复杂度:sort函数
被调用了
l
o
g
2
n
log_{2}n
log2n次,sort函数
中的merge函数
的复杂度为
n
n
n,所有复杂度为
n
∗
l
o
g
2
n
n*log_{2}n
n∗log2n
逆序是在归并排序中统计的,当归并的时候,左边的数字大于右边,就是一个逆序。代码如下:
class Solution {
public:
int count;
public:
void sort(vector<int>& nums, int left, int right) //分治 排序
{
if(left+1==right) //只有两个元素
{
if(nums[left]>nums[right])
{
this->count++;
int tmp = nums[left];
nums[left] = nums[right];
nums[right] = tmp;
}
return;
} //只有一个元素
else if(left==right)
return;
int center = (left+right)/2;
sort(nums, left, center); //左子串
sort(nums, center+1, right); //右子串
merge(nums, left, center, right); //归并
}
void merge(vector<int>& nums, int left, int center, int right)
{
int i=0;
int tmp[right-left+1];
int l_pos = left, r_pos = center+1;
while(l_pos<=center && r_pos<=right)
{
if(nums[l_pos]>nums[r_pos]) //左边比右边大
{
this->count += center-l_pos+1; //当前左子串的这个元素的左侧元素们都比右子串当前元素大
tmp[i++] = nums[r_pos];
r_pos++;
}
else
{
tmp[i++] = nums[l_pos];
l_pos++;
}
}
while(l_pos<=center)
{
tmp[i++] = nums[l_pos];
l_pos++;
}
while(r_pos<=right)
{
tmp[i++] = nums[r_pos];
r_pos++;
}
for(int k=left,j=0; k<=right; k++,j++)
nums[k] = tmp[j];
}
int reversePairs(vector<int>& nums) {
if(nums.size()==0)
return 0;
this->count = 0;
sort(nums, 0, nums.size()-1);
return this->count;
}
};
//暴力解决
// int count = 0;
// int size = nums.size();
// for(int i=0; i<size; i++)
// {
// int j=i+1;
// while(j<size)
// {
// if(nums[i]>nums[j])
// {
// count++;
// }
// j++;
// }
// }
// return count;
虽然可能讲的不是很透彻,因为归并排序我也只是会写,我觉得我没有摸到核心,但积少成多!