Leetcode493——Reverse Pairs

垃圾如我,先mark一下吧,听说树状数组可以更简便,然而一直还没看之先mark一下吧


既然不用树状数组,那就只能用merge&sort和bst了,大神说了bst会超时,只能用avl,然后我试了试bst还真的会超时:


class Solution {
public:
    int sum = 0;
    struct node{
        node* r, *l;
        int num, count;
        node() :r(NULL), l(NULL), num(0), count(0){};
        node(int num, int count) :r(NULL), l(NULL), num(num), count(count){};
    };
    
    void Add(node* &u, int n, int count){
        if(u == NULL){
            u = new node(n, count);
        }
        else{
            if(n >= u->num){
                Add(u->r, n, 0);
            }else{
                u->count++;
                Add(u->l, n, 0);
            }
        }
    }
    
    void countNum(node* &u, int n, int & ans){
        if(u == NULL) return;
        else{
            if(n > 2 * u->num){
                ans += u->count + 1;
                countNum(u->r, n, ans);
            }else{
                countNum(u->l, n, ans);
            }
        }
        
    }
    
    int reversePairs(vector<int>& nums) {
        node* root = NULL;
        int ans = 0;
        for(auto i = nums.rbegin(); i != nums.rend(); i++){
            countNum(root, *i, ans);
            Add(root, *i, 0);
        }
        return ans;
    }
};


大意就是对每个倒序数先查询到底,计算出sum来,然后按照正常(小于就左子树,大于就右子树)插入(真的很麻烦,估计底下的树枝长的不得了,还不如二分暴力查找)


再就是merge&sort + 二分查找大法:


int countPairs(vector<int> &nums){
    if(nums.size() <= 1) return 0;
    
    int n = (int)nums.size();
    int ans = 0;
    
    vector<int> a(nums.begin(), nums.begin() + n/2);
    vector<int> b(nums.begin() + n/2, nums.end());
    
    ans += countPairs(a);
    ans += countPairs(b);
    
    int an = 0, bn = 0;
    for(int i = 0; i<n; i++){
        if(an != a.size() && (bn == b.size() || b[bn] >= a[an])){
            
            long temp = ceil(1.0*a[an]/2);
            
            int low = 0, high = (int)b.size();
            while(low <= high){
                int mid = (low + high) / 2;
                if(b[mid] < temp) low = mid + 1;
                else high = mid;
                if(low == high) break;
            }
            ans += low;
            nums[i] = a[an++];
        }
        else{
            nums[i] = b[bn++];
        }
    }
    return ans;
}

大意就是先分再和,合的时候(求逆序对和的时候直接比较完大小就可以sum+=bn了),但是这里就不能直接sum+=,需要用二分法找到真正的bn位置,然后sum+=bn。(暴力暴力)


最后就是树状数组了

493. Reverse Pairs

不负责任粘贴他人代码

public class Solution {
    public int reversePairs(int[] nums) {
        int res = 0;
        int n = nums.length;
        if(n == 0) return res;
        // reflection
        Map<Long, Integer> map = new HashMap();
        long[] sorted = new long[2*n];
        for(int i = 0; i < n; i++) {
            sorted[2*i] = nums[i];
            sorted[2*i + 1] = (long) nums[i] * 2;
        }
        Arrays.sort(sorted);
        int idx = 1;
        for(long num : sorted) {
            if(!map.containsKey(num)) map.put(num, idx++);
        }
        
        BIT t = new BIT(idx);
        int sum = 0;
        for(int j = 0; j < n; j++) {
            // find how many number > 2 * nums[j]
            long num = (long) nums[j];
            res += sum - t.sum(map.get(num*2));
            t.add(map.get(num), 1);
            sum++;
        }
        return res;
    }
    
    class BIT {
        int n;
        int[] tree;
        BIT(int n) { this.n = n; tree = new int[n]; }
        
        protected int sum(int i) {
            int res = 0;
            while(i > 0) {
                res += tree[i];
                i -= i & -i;
            }
            return res;
        }
        
        protected void add(int i, int val) {
            while(i < n) {
                tree[i] += val;
                i += i & -i;
            }
        }
    }
}

然后困扰了两天的题目就要继续困扰下去了。



参考:

 

Reverse Pairs (第二周:分治法)


 

【算法】逆序对问题的四种解法(归并排序,BST,树状数组,线段树)及变形



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值