LeetCode 记录-1697. 检查边长度限制的路径是否存在

59 阅读2分钟

LeetCode 记录-1697. 检查边长度限制的路径是否存在

我的解法

思路

image.png

可以看到,对于 queries 中的每一个查询项,其中queries[j]=[pj,qj,limitj]queries[j] = [p_j,q_j,limit_j],我们可以使用limitjlimit_j将无向图边集edgeListedgeList中互通且满足长度小于limitjlimit_j节点放在一个集合,当查询的两个节点pjp_j,qjq_j处在同一个集合的时候,表明查询有效,返回 true,否则返回 false。

这个思路可以使用并查集来实现。

什么是并查集?

并查集是一种用于管理元素所属集合的数据结构,实现为一个森林,其中每棵树表示一个集合,树中的节点表示对应集合中的元素。

顾名思义,并查集支持两种操作:

  • 合并(Union): 合并两个元素所属集合(合并对应的树)。
  • 查询(Find): 查询某个元素所属集合(查询对应的树的根节点),还可以用于判断两个元素是否属于同一集合。

官方解法 1: 离线查询 + 并查集

思路

image.png

官方也是采用了并查集的方法,但同时还采用了离线查询,只要建立一个并查集就可以查询出所有的结果。 我们可以通过官方的思路看到:

  • 如果queriesquerieslimitlimit是非递减的,显然上一次查询的并查集里的边都是满足当前查询的limitlimit需求的,我们只需要将剩余的长度小于limitlimit的边加入并查集中即可。所以首先将queriesquerieslimitlimit从小到大进行排序。
  • 同时,将edgeListedgeList按边长度从小到大进行排序,使用kk指向上一次查询中不满足limitlimit要求的长度的最小的边,初始时k=0k=0

在满足以上要求后,我们就可以遍历一遍queriesqueriesedgeListedgeList来实现查询所有的结果。

代码

/**
 * @param {number} n
 * @param {number[][]} edgeList
 * @param {number[][]} queries
 * @return {boolean[]}
 */
var distanceLimitedPathsExist = function (n, edgeList, queries) {
  edgeList.sort((a, b) => a[2] - b[2]);
  const index = new Array(queries.length).fill(0);
  for (let i = 0; i < queries.length; i++) {
    index[i] = i;
  }
  index.sort((a, b) => queries[a][2] - queries[b][2]);
  const uf = new Array(n).fill(0);
  for (let i = 0; i < n; i++) {
    uf[i] = i;
  }

  const ans = new Array(queries.length).fill(0);
  let k = 0;
  for (let i of index) {
    while (k < edgeList.length && edgeList[k][2] < queries[i][2]) {
      merge(uf, edgeList[k][0], edgeList[k][1]);
      k++;
    }

    ans[i] = find(uf, queries[i][0]) === find(uf, queries[i][1]);
  }

  return ans;
};

const find = (uf, x) => {
  if (uf[x] === x) {
    return x;
  }

  return (uf[x] = find(uf, uf[x]));
};

const merge = (uf, x, y) => {
  x = find(uf, x);
  y = find(uf, y);

  uf[y] = x;
};

复杂度分析

时间复杂度

O(ElogE+mlogm+(E+m)logn+n)O(ElogE+mlogm+(E+m)logn+n),其中EEedgeListedgeList的长度,mmqueriesqueries的长度,nn是点数。对degeListdegeListqueriesqueries进行排序分别需要O(ElogE)O(ElogE)O(mlogm)O(mlogm),并查集初始化需要O(n)O(n),并查集查询和合并总共需要O((E+m)logn)O((E+m)logn)

空间复杂度

O(logE+m+n)O(logE+m+n),保存并查集需要O(n)O(n)的空间,保存indexindex需要O(m)O(m)的空间,以及排序需要的栈空间。