LeetCode 题解工作台

统计点对的数目

给你一个无向图,无向图由整数 n ,表示图中节点的数目,和 edges 组成,其中 edges[i] = [u i , v i ] 表示 u i 和 v i 之间有一条无向边。同时给你一个代表查询的整数数组 queries 。 第 j 个查询的答案是满足如下条件的点对 (a, b) 的数目: a c…

category

7

题型

code_blocks

5

代码语言

hub

3

相关题

当前训练重点

困难 · 数组·哈希·扫描

bolt

答案摘要

根据题目,我们可以知道,与点对 $(a, b)$ 相连的边数等于“与 相连的边数”加上“与 相连的边数”,再减去同时与 和 相连的边数。 因此,我们可以先用数组 统计与每个点相连的边数,用哈希表 统计每个点对的数量。

Interview AiBox logo

Interview AiBox 实时 AI 助手,陪你讲清 数组·哈希·扫描 题型思路

试试 AiBox 面试助手arrow_forward
description

题目描述

给你一个无向图,无向图由整数 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
lightbulb

解题思路

方法一:哈希表 + 排序 + 二分查找

根据题目,我们可以知道,与点对 (a,b)(a, b) 相连的边数等于“与 aa 相连的边数”加上“与 bb 相连的边数”,再减去同时与 aabb 相连的边数。

因此,我们可以先用数组 cntcnt 统计与每个点相连的边数,用哈希表 gg 统计每个点对的数量。

然后,对于每个查询 qq,我们可以枚举 aa,对于每个 aa,我们可以通过二分查找找到第一个满足 cnt[a]+cnt[b]>qcnt[a] + cnt[b] > qbb,先将数量累加到当前查询的答案中,然后减去一部分重复的边。

时间复杂度 O(q×(n×logn+m))O(q \times (n \times \log n + m)),空间复杂度 O(n+m)O(n + m)。其中 nnmm 分别是点数和边数,而 qq 是查询数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Solution:
    def countPairs(
        self, n: int, edges: List[List[int]], queries: List[int]
    ) -> List[int]:
        cnt = [0] * n
        g = defaultdict(int)
        for a, b in edges:
            a, b = a - 1, b - 1
            a, b = min(a, b), max(a, b)
            cnt[a] += 1
            cnt[b] += 1
            g[(a, b)] += 1

        s = sorted(cnt)
        ans = [0] * len(queries)
        for i, t in enumerate(queries):
            for j, x in enumerate(s):
                k = bisect_right(s, t - x, lo=j + 1)
                ans[i] += n - k
            for (a, b), v in g.items():
                if cnt[a] + cnt[b] > t and cnt[a] + cnt[b] - v <= t:
                    ans[i] -= 1
        return ans
speed

复杂度分析

指标
时间Depends on the final approach
空间Depends on the final approach
psychology

面试官常问的追问

外企场景
  • question_mark

    The candidate efficiently uses hash tables to avoid recalculating pair degrees multiple times.

  • question_mark

    The solution scales well to larger graphs by leveraging precomputation and optimized queries.

  • question_mark

    The candidate understands how to handle edge cases, such as nodes with no edges or densely connected nodes.

warning

常见陷阱

外企场景
  • error

    Not handling graphs with nodes that have no edges, leading to incorrect degree calculations.

  • error

    Using brute force to calculate pairs for each query, which may lead to performance issues for large graphs.

  • error

    Misunderstanding how to efficiently use hash tables, which could result in unnecessary recomputation.

swap_horiz

进阶变体

外企场景
  • arrow_right_alt

    The problem can be modified by changing the threshold in each query, making it more dynamic.

  • arrow_right_alt

    You could add a variation where the graph is directed, affecting how incident pairs are calculated.

  • arrow_right_alt

    Another variant might involve returning the top N node pairs based on the degree sum for each query.

help

常见问题

外企场景

统计点对的数目题解:数组·哈希·扫描 | LeetCode #1782 困难