力扣1782.统计点对的数目(困难)

摘要

力扣1782.统计点对的数目(困难)

题目

给你一个无向图,无向图由整数 n ,表示图中节点的数目,和 edges 组成,其中 edges[i] = [ui, vi] 表示 ui 和 vi 之间有一条无向边。同时给你一个代表查询的整数数组 queries 。

第 j 个查询的答案是满足如下条件的点对 (a, b) 的数目:
a < b
cnt 是与 a 或者 b 相连的边的数目,且 cnt 严格大于 queries[j] 。
请你返回一个数组 answers ,其中 answers.length == queries.length 且 answers[j] 是第 j 个查询的答案。

请注意,图中可能会有 重复边

示例 1:
在这里插入图片描述
输入:n = 4, edges = [[1,2],[2,4],[1,3],[2,3],[2,1]], queries = [2,3]
输出:[6,5]
解释:每个点对中,与至少一个点相连的边的数目如上图所示。
answers[0] = 6。所有的点对(a, b)中边数和都大于2,故有6个;
answers[1] = 5。所有的点对(a, b)中除了(3,4)边数等于3,其它点对边数和都大于3,故有5个。
示例 2:
输入:n = 5, edges = [[1,5],[1,5],[3,4],[2,5],[1,3],[5,1],[2,3],[2,5]], queries = [1,2,3,4,5]
输出:[10,10,9,8,6]

提示:
2 <= n <= 2 * 104
1 <= edges.length <= 105
1 <= ui, vi <= n
ui != vi!
1 <= queries.length <= 20
0 <= queries[j] < edges.length

解题思路

1、对各点的度(连接数)进行计算
2、建立点对,对重复连接数进行处理,获得每个点对中至少一个点相连的边的数目
3、根据查询条件,对数组进行遍历,查询,返回输出

代码

public class CountPairs {
    public int[] countPairs(int n, int[][] edges, int[] queries) {
        //对输入n进行校验
        if (n<=0){
            System.out.println("输入的n值不合法!请重新输入!");
        }
        /**
         * 1、对各点连接数进行确认
         * 2、建立点对,对重复连接数进行处理,获得每个点对中至少一个点相连的边的数目
         * 3、根据查询条件,对数组进行遍历,查询,返回输出
         */
        int[] degree = new int[n];
        Map<Integer, Integer> cnt = new HashMap<Integer, Integer>();
        for (int[] edge : edges) {
            int x = edge[0] - 1, y = edge[1] - 1;
            if (x > y) {
                int temp = x;
                x = y;
                y = temp;
            }
            degree[x]++;
            degree[y]++;
            cnt.put(x * n + y, cnt.getOrDefault(x * n + y, 0) + 1);
        }

        int[] arr = Arrays.copyOf(degree,n);

        int[] ans = new int[queries.length];

        Arrays.sort(arr);

        for (int m = 0 ; m < queries.length ;m++){
            int bound = queries[m], total = 0;

            for (int i = 0;i < n ; i++){
                int j = binarySearch(arr,i+1,n-1,bound-arr[i]);
                total += n - j;
            }

            for (Map.Entry<Integer,Integer> entry : cnt.entrySet()){

                int val = entry.getKey(), freq = entry.getValue();

                int x = val/n, y = val % n;

                if (degree[x] + degree[y] > bound && degree[x]+ degree[y]- freq <= bound){
                    total--;
                }
            }
            ans[m]=total;
        }
        return ans;
    }

    public int binarySearch(int[] arr, int left, int right, int target){

        int ans = right+1;
        while (left <= right){
            int mid = (left+right)>>1;
            if (arr[mid] < target){
                left = mid + 1;
            } else {
                right = mid -1;
                ans = mid;
            }
        }
        return ans;
    }
}

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值