leetcode【困难】2179、统计数组中好三元组数目

给你两个下标从 0 开始且长度为 n 的整数数组 nums1 和 nums2 ,两者都是 [0, 1, …, n - 1] 的 排列 。

好三元组 指的是 3 个 互不相同 的值,且它们在数组 nums1 和 nums2 中出现顺序保持一致。换句话说,如果我们将 pos1v 记为值 v 在 nums1 中出现的位置,pos2v 为值 v 在 nums2 中的位置,那么一个好三元组定义为 0 <= x, y, z <= n - 1 ,且 pos1x < pos1y < pos1zpos2x < pos2y < pos2z 都成立的 (x, y, z) 。

请你返回好三元组的 总数目 。3 <= n <= 100000

示例 1:

输入:nums1 = [2,0,1,3], nums2 = [0,1,2,3]
输出:1
解释:
总共有 4 个三元组 (x,y,z) 满足 pos1x < pos1y < pos1z ,
分别是 (2,0,1)(2,0,3)(2,1,3)(0,1,3) 。
这些三元组中,只有 (0,1,3) 满足 pos2x < pos2y < pos2z 。
所以只有 1 个好三元组。

示例 2:

输入:nums1 = [4,0,1,3,2], nums2 = [4,1,0,2,3]
输出:4
解释:总共有 4 个好三元组 (4,0,3)(4,0,2)(4,1,3)(4,1,2)

思路:

nums1:[4,0,1,3,2] -> [0,1,2,3,4] 记录nums1中数字的位置(或者说映射关系)
nums2:[4,1,0,2,3] -> [0,2,1,4,3] 让nums2按照这个顺序排列
nums2左边小于当前数,有几对[0,1,1,3,3]
nums2右边大于当前数,有几对[4,2,2,0,0]
ans = sum(left[i] * right[i]);

注意:树状数组的下标是 1 … n,而给定的数组下标是 0 … n-1

class Solution {
    public long goodTriplets(int[] nums1, int[] nums2) {
        int n=nums1.length;
        long res=0;
        Map<Integer, Integer> hash = new HashMap<>();
        for (int i = 0; i < n; i++) hash.put(nums1[i], i);
        for (int i = 0; i < n; i++) nums2[i] = hash.get(nums2[i]);
        BIT bit=new BIT(100005);
        for(int i=0;i<n;i++){           
            int l = bit.query(nums2[i]+1); // 左边小于nums2[i]的数
            int t = i - l; // 左边大于nums2[i]的数
            int r = (n - nums2[i] - 1) - t; // 右边大于nums2[i]的数
            bit.update(nums2[i]+1); 
            res += 1L * l * r;
        }
        return res;
    }
}

class BIT {
    private int[] tree;
    private int n;

    public BIT(int n) {
        this.n = n;
        this.tree = new int[n + 1];
    }

    public static int lowbit(int x) {
        return x & (-x);
    }

    public int query(int x) {
        int ret = 0;
        while (x != 0) {
            ret += tree[x];
            x -= lowbit(x);
        }
        return ret;
    }

    public void update(int x) {
        while (x <= n) {
            ++tree[x];
            x += lowbit(x);
        }
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值