You are given a 2D integer array properties having dimensions n x m and an integer k.
Define a function intersect(a, b) that returns the number of distinct integers common to both arrays a and b.
Construct an undirected graph where each index i corresponds to
properties[i]. There is an edge between node i and node j if and only if
intersect(properties[i], properties[j]) >= k, where i and j are in the range [0, n - 1] and i != j.
Return the number of connected components in the resulting graph.
Input: properties =[[1,2],[1,1],[3,4],[4,5],[5,6],[7,7]], k =1Output: 3Explanation:
The graph formed has 3 connected components:
Input: properties =[[1,2,3],[2,3,4],[4,3,5]], k =2Output: 1Explanation:
The graph formed has 1 connected component:
Input: properties =[[1,1],[1,1]], k =2Output: 2Explanation:
`intersect(properties[0], properties[1]) = 1`, which is less than `k`. This
means there is no edge between `properties[0]` and `properties[1]`in the
graph.
We can model the problem as a graph where each node is a property, and an edge exists if two properties share at least k distinct integers. The number of connected components can be found using DFS or Union-Find.
#include<vector>#include<unordered_set>usingnamespace std;
classSolution {
public:int countComponents(vector<vector<int>>& properties, int k) {
int n = properties.size();
vector<vector<int>> graph(n);
for (int i =0; i < n; ++i) {
unordered_set<int> seti(properties[i].begin(), properties[i].end());
for (int j = i+1; j < n; ++j) {
unordered_set<int> setj(properties[j].begin(), properties[j].end());
int cnt =0;
for (int x : seti) if (setj.count(x)) ++cnt;
if (cnt >= k) {
graph[i].push_back(j);
graph[j].push_back(i);
}
}
}
vector<bool> vis(n);
int ans =0;
function<void(int)> dfs = [&](int u) {
vis[u] = true;
for (int v : graph[u]) if (!vis[v]) dfs(v);
};
for (int i =0; i < n; ++i) if (!vis[i]) { ++ans; dfs(i); }
return ans;
}
};
import java.util.*;
classSolution {
publicintcountComponents(int[][] properties, int k) {
int n = properties.length;
List<List<Integer>> graph =new ArrayList<>();
for (int i = 0; i < n; ++i) graph.add(new ArrayList<>());
for (int i = 0; i < n; ++i) {
Set<Integer> seti =new HashSet<>();
for (int x : properties[i]) seti.add(x);
for (int j = i+1; j < n; ++j) {
Set<Integer> setj =new HashSet<>();
for (int x : properties[j]) setj.add(x);
int cnt = 0;
for (int x : seti) if (setj.contains(x)) cnt++;
if (cnt >= k) {
graph.get(i).add(j);
graph.get(j).add(i);
}
}
}
boolean[] vis =newboolean[n];
int ans = 0;
for (int i = 0; i < n; ++i) {
if (!vis[i]) {
ans++;
dfs(i, graph, vis);
}
}
return ans;
}
privatevoiddfs(int u, List<List<Integer>> graph, boolean[] vis) {
vis[u]=true;
for (int v : graph.get(u)) if (!vis[v]) dfs(v, graph, vis);
}
}
classSolution {
funcountComponents(properties: Array<IntArray>, k: Int): Int {
val n = properties.size
val graph = Array(n) { mutableListOf<Int>() }
for (i in0 until n) {
val seti = properties[i].toSet()
for (j in i+1 until n) {
val setj = properties[j].toSet()
val cnt = seti.intersect(setj).size
if (cnt >= k) {
graph[i].add(j)
graph[j].add(i)
}
}
}
val vis = BooleanArray(n)
fundfs(u: Int) {
vis[u] = truefor (v in graph[u]) if (!vis[v]) dfs(v)
}
var ans = 0for (i in0 until n) {
if (!vis[i]) { ans++; dfs(i) }
}
return ans
}
}
from typing import List
classSolution:
defcountComponents(self, properties: List[List[int]], k: int) -> int:
n = len(properties)
graph = [[] for _ in range(n)]
sets = [set(row) for row in properties]
for i in range(n):
for j in range(i+1, n):
if len(sets[i] & sets[j]) >= k:
graph[i].append(j)
graph[j].append(i)
vis = [False] * n
defdfs(u):
vis[u] =Truefor v in graph[u]:
ifnot vis[v]:
dfs(v)
ans =0for i in range(n):
ifnot vis[i]:
ans +=1 dfs(i)
return ans
⏰ Time complexity: O(n^2 * m), where n is the number of properties and m is the number of elements in each property. For each pair, we compute intersection in O(m).
🧺 Space complexity: O(n * m) for storing sets and the adjacency list.