概述
LeetCode——第二十天
面试题51. 数组中的逆序对
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。
示例 1:
输入: [7,5,6,4]
输出: 5
限制:
0 <= 数组长度 <= 50000
分析:逆序对,经典题目。用了两个for循环,结果超时了,哈哈哈,也很正常。然后印象中二叉树就是类似堆的线段树还是啥,可以一边更新一边统计,不过就接触一次,忘了。通过归并排序,原理很简单,大家看看就知道了。
暴力破解代码
class Solution {
public:
int reversePairs(vector<int>& nums) {
int res = 0;
for(int i=0;i<nums.size();i++){
for(int j=i+1;j<nums.size();j++){
if(nums[i]>nums[j])res++;
}
}
return res;
}
};
归并排序代码
class Solution {
private:
int res = 0;
public:
//归并排序算法
void mergesort(vector<int>& nums,vector<int>& temp,int lo,int hi){
if(lo>=hi) return;//出口
int mid = lo+(hi-lo)/2;
mergesort(nums,temp,lo,mid);
mergesort(nums,temp,mid+1,hi);
int i=lo,j=mid+1,k=lo;
//子序列排序过程
while(i!=mid+1 && j!=hi+1){
if(nums[i]>nums[j]){
temp[k++] = nums[j++];
res+=mid-i+1;
/*这里统计,如果左边比右边大,那么就是逆序,
并且左边剩下都会比当前右边这个值大,所以全部加进去*/
}
else temp[k++] = nums[i++];
//需要注意,如果右边等于或者大于左边,是正常情况,继续排序即可
}
while(i!=mid+1) temp[k++] = nums[i++];
while(j!=hi+1) temp[k++] = nums[j++];
for(int i=lo;i<=hi;i++) nums[i] = temp[i];
}
int reversePairs(vector<int>& nums) {
vector<int> temp(nums.size(),0);
mergesort(nums,temp,0,nums.size()-1);
return res;
}
};
**归并排序如果有不懂可以看看我之前写的。各类排序算法
**
离散化树状数组代码(官方)
**拖了好几天,最近学得多,唉。这个是树状数组,跟线段树还是有点差别,具体可以参考这篇博客:
树状数组
还是这个视频:
视频
讲得很清楚了,主要是要理解前缀和与lowbit之间的关系,官方这边对数组离散化处理了下,避免很多0,要维护一个很大的数组。
**
class BIT {
private:
vector<int> tree;
int n;
public:
BIT(int _n): n(_n), tree(_n + 1) {}
static int lowbit(int x) {
return x & (-x); //这里返回的是x低位开始到第一个1以及0的数,比如88会得到8
//具体为什么这样去看看博客和视频
}
int query(int x) {
int ret = 0;
while (x) {
ret += tree[x];//这里是将树状数组前缀和相加,减lowbit刚好就是前缀和
x -= lowbit(x);
}
return ret;
}
void update(int x) {
while (x <= n) {//只需要更新父节点的就可以,加lowbit刚好是父节点
++tree[x];
x += lowbit(x);
}
}
};
class Solution {
public:
int reversePairs(vector<int>& nums) {
int n = nums.size();
vector<int> tmp = nums;
// 离散化
sort(tmp.begin(), tmp.end());
for (int& num: nums) {
num = lower_bound(tmp.begin(), tmp.end(), num) - tmp.begin() + 1;
}
// 树状数组统计逆序对
BIT bit(n);
int ans = 0;
for (int i = n - 1; i >= 0; --i) {
ans += bit.query(nums[i] - 1);
bit.update(nums[i]);
}
return ans;
}
};
作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/shu-zu-zhong-de-ni-xu-dui-lcof/solution/shu-zu-zhong-de-ni-xu-dui-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
2.总结
树状数组太神奇了。前辈们设计计算机用二进制真的是考虑很多很多,之前组成原理里面也乘除法也是,以后量子计算机就更神奇了。
最后
以上就是称心黄豆为你收集整理的LeetCode——第二十天(数组中的逆序对)(树状数组)的全部内容,希望文章能够帮你解决LeetCode——第二十天(数组中的逆序对)(树状数组)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复