列表

详情


3493. 属性图

给你一个二维整数数组 properties,其维度为 n x m,以及一个整数 k

定义一个函数 intersect(a, b),它返回数组 ab 共有的不同整数的数量

构造一个 无向图,其中每个索引 i 对应 properties[i]。如果且仅当 intersect(properties[i], properties[j]) >= k(其中 ij 的范围为 [0, n - 1]i != j),节点 i 和节点 j 之间有一条边。

返回结果图中 连通分量 的数量。

 

示例 1:

输入: properties = [[1,2],[1,1],[3,4],[4,5],[5,6],[7,7]], k = 1

输出: 3

解释:

生成的图有 3 个连通分量:

示例 2:

输入: properties = [[1,2,3],[2,3,4],[4,3,5]], k = 2

输出: 1

解释:

生成的图有 1 个连通分量:

示例 3:

输入: properties = [[1,1],[1,1]], k = 2

输出: 2

解释:

intersect(properties[0], properties[1]) = 1,小于 k。因此在图中 properties[0]properties[1] 之间没有边。

 

提示:

原站题解

去查看

上次编辑到这里,代码来自缓存 点击恢复默认模板
class Solution { public: int numberOfComponents(vector<vector<int>>& properties, int k) { } };

python3 解法, 执行用时: 235 ms, 内存消耗: 18.3 MB, 提交时间: 2025-03-24 23:38:53

class UnionFind:
    def __init__(self, n: int):
        # 一开始有 n 个集合 {0}, {1}, ..., {n-1}
        # 集合 i 的代表元是自己
        self._fa = list(range(n))  # 代表元
        self.cc = n  # 连通块个数

    # 返回 x 所在集合的代表元
    # 同时做路径压缩,也就是把 x 所在集合中的所有元素的 fa 都改成代表元
    def find(self, x: int) -> int:
        # 如果 fa[x] == x,则表示 x 是代表元
        if self._fa[x] != x:
            self._fa[x] = self.find(self._fa[x])  # fa 改成代表元
        return self._fa[x]

    # 把 from 所在集合合并到 to 所在集合中
    def merge(self, from_: int, to: int) -> None:
        x, y = self.find(from_), self.find(to)
        if x == y:  # from 和 to 在同一个集合,不做合并
            return
        self._fa[x] = y  # 合并集合。修改后就可以认为 from 和 to 在同一个集合了
        self.cc -= 1  # 合并后,连通块个数减少了 1

class Solution:
    def numberOfComponents(self, properties: List[List[int]], k: int) -> int:
        sets = list(map(set, properties))
        uf = UnionFind(len(properties))
        for i, a in enumerate(sets):
            for j, b in enumerate(sets[:i]):
                if len(a & b) >= k:
                    uf.merge(j, i)
        return uf.cc

python3 解法, 执行用时: 66 ms, 内存消耗: 18.1 MB, 提交时间: 2025-03-24 23:38:37

class UnionFind:
    def __init__(self, n: int):
        # 一开始有 n 个集合 {0}, {1}, ..., {n-1}
        # 集合 i 的代表元是自己
        self._fa = list(range(n))  # 代表元
        self.cc = n  # 连通块个数

    # 返回 x 所在集合的代表元
    # 同时做路径压缩,也就是把 x 所在集合中的所有元素的 fa 都改成代表元
    def find(self, x: int) -> int:
        # 如果 fa[x] == x,则表示 x 是代表元
        if self._fa[x] != x:
            self._fa[x] = self.find(self._fa[x])  # fa 改成代表元
        return self._fa[x]

    # 把 from 所在集合合并到 to 所在集合中
    def merge(self, from_: int, to: int) -> None:
        x, y = self.find(from_), self.find(to)
        if x == y:  # from 和 to 在同一个集合,不做合并
            return
        self._fa[x] = y  # 合并集合。修改后就可以认为 from 和 to 在同一个集合了
        self.cc -= 1  # 合并后,连通块个数减少了 1

class Solution:
    def numberOfComponents(self, properties: List[List[int]], k: int) -> int:
        sets = [reduce(or_, (1 << x for x in a)) for a in properties]
        uf = UnionFind(len(properties))
        for i, a in enumerate(sets):
            for j, b in enumerate(sets[:i]):
                if (a & b).bit_count() >= k:
                    uf.merge(j, i)
        return uf.cc

java 解法, 执行用时: 232 ms, 内存消耗: 44.9 MB, 提交时间: 2025-03-24 23:38:15

class UnionFind {
    private final int[] fa;
    public int cc; // 连通块个数

    UnionFind(int n) {
        fa = new int[n];
        cc = n;
        for (int i = 0; i < n; i++) {
            fa[i] = i;
        }
    }

    public int find(int x) {
        if (fa[x] != x) {
            fa[x] = find(fa[x]);
        }
        return fa[x];
    }

    public void merge(int from, int to) {
        int x = find(from);
        int y = find(to);
        if (x == y) {
            return;
        }
        fa[x] = y;
        cc--;
    }
}

class Solution {
    public int numberOfComponents(int[][] properties, int k) {
        int n = properties.length;
        int m = properties[0].length;
        Set<Integer>[] sets = new HashSet[n];
        Arrays.setAll(sets, i -> new HashSet<>(m));
        for (int i = 0; i < n; i++) {
            for (int x : properties[i]) {
                sets[i].add(x);
            }
        }

        UnionFind u = new UnionFind(n);
        for (int i = 0; i < n; i++) {
            Set<Integer> a = sets[i];
            for (int j = 0; j < i; j++) {
                int cnt = 0;
                for (int x : sets[j]) {
                    if (a.contains(x)) {
                        cnt++;
                    }
                }
                if (cnt >= k) {
                    u.merge(i, j);
                }
            }
        }
        return u.cc;
    }
}

cpp 解法, 执行用时: 189 ms, 内存消耗: 48.7 MB, 提交时间: 2025-03-24 23:38:02

class UnionFind {
    vector<int> fa;

public:
    int cc; // 连通块个数

    UnionFind(int n) : fa(n), cc(n) {
        ranges::iota(fa, 0);
    }

    int find(int x) {
        if (fa[x] != x) {
            fa[x] = find(fa[x]);
        }
        return fa[x];
    }

    void merge(int from, int to) {
        int x = find(from), y = find(to);
        if (x == y) {
            return;
        }
        fa[x] = y;
        cc--;
    }
};

class Solution {
public:
    int numberOfComponents(vector<vector<int>>& properties, int k) {
        int n = properties.size();
        vector<unordered_set<int>> sets(n);
        for (int i = 0; i < n; i++) {
            sets[i] = unordered_set(properties[i].begin(), properties[i].end());
        }

        UnionFind uf(n);
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < i; j++) {
                int cnt = 0;
                for (int x : sets[j]) {
                    if (sets[i].contains(x)) {
                        cnt++;
                    }
                }
                if (cnt >= k) {
                    uf.merge(i, j);
                }
            }
        }
        return uf.cc;
    }
};

golang 解法, 执行用时: 293 ms, 内存消耗: 8.6 MB, 提交时间: 2025-03-24 23:37:49

type uf struct {
	fa []int
	cc int
}

func newUnionFind(n int) uf {
	fa := make([]int, n)
	for i := range fa {
		fa[i] = i
	}
	return uf{fa, n}
}

func (u uf) find(x int) int {
	if u.fa[x] != x {
		u.fa[x] = u.find(u.fa[x])
	}
	return u.fa[x]
}

func (u *uf) merge(from, to int) {
	x, y := u.find(from), u.find(to)
	if x == y {
		return
	}
	u.fa[x] = y
	u.cc--
}

func numberOfComponents(properties [][]int, k int) int {
	sets := make([]map[int]bool, len(properties))
	for i, a := range properties {
		sets[i] = map[int]bool{}
		for _, x := range a {
			sets[i][x] = true
		}
	}

	u := newUnionFind(len(properties))
	for i, a := range sets {
		for j, b := range sets[:i] {
			cnt := 0
			for x := range b {
				if a[x] {
					cnt++
				}
			}
			if cnt >= k {
				u.merge(i, j)
			}
		}
	}
	return u.cc
}

上一题