Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 73 additions & 44 deletions solution/2000-2099/2092.Find All People With Secret/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,21 @@ tags:

<!-- solution:start -->

### 方法一:BFS
### 方法一:模拟 + 图遍历

本题的核心思路是通过模拟会议的传播过程来找出所有最终会知道秘密的人。我们可以将每次会议视为一个无向图的边,其中每个参与者是图中的一个节点,会议的时间是节点之间连接的边的“时间戳”。在每个时间点,我们遍历所有会议,利用广度优先搜索(BFS)来模拟秘密的传播。

创建一个布尔数组 $\textit{vis}$ 来记录每个人是否知道秘密。初始时,$\textit{vis}[0] = \text{true}$ 和 $\textit{vis}[\textit{firstPerson}] = \text{true}$,表示0号和 $\textit{firstPerson}$ 已经知道秘密。

我们首先按照每个会议的时间进行排序,以确保每次遍历时能够按照正确的顺序处理会议。

接下来,处理每一组相同时间的会议。对于每一组相同时间的会议(即 $\textit{meetings}[i][2] = \textit{meetings}[i+1][2]$),我们将它们视为同一时刻发生的事件。对于每个会议,记录参与者的关系,并将这些参与者加入一个集合中。

然后,我们利用 BFS 来传播秘密。对于当前时间点的所有参与者,如果其中有任何人已经知道秘密,我们将通过 BFS 遍历该参与者的相邻节点(即会议中的其他参与者),将他们标记为知道秘密。这个过程会继续传播,直到所有在这次会议中能够知道秘密的人都被更新。

当所有会议处理完毕后,遍历 $\textit{vis}$ 数组,将所有知道秘密的人的编号加入结果列表并返回。

时间复杂度 $(m \times \log m + n)$,空间复杂度 $O(n)$。其中 $m$ 和 $n$ 分别是会议数量和专家数量。

<!-- tabs:start -->

Expand Down Expand Up @@ -137,8 +151,9 @@ class Solution {
Arrays.sort(meetings, Comparator.comparingInt(a -> a[2]));
for (int i = 0; i < m;) {
int j = i;
for (; j + 1 < m && meetings[j + 1][2] == meetings[i][2]; ++j)
;
for (; j + 1 < m && meetings[j + 1][2] == meetings[i][2];) {
++j;
}
Map<Integer, List<Integer>> g = new HashMap<>();
Set<Integer> s = new HashSet<>();
for (int k = i; k <= j; ++k) {
Expand All @@ -156,7 +171,7 @@ class Solution {
}
while (!q.isEmpty()) {
int u = q.poll();
for (int v : g.getOrDefault(u, Collections.emptyList())) {
for (int v : g.getOrDefault(u, List.of())) {
if (!vis[v]) {
vis[v] = true;
q.offer(v);
Expand Down Expand Up @@ -189,8 +204,9 @@ public:
});
for (int i = 0, m = meetings.size(); i < m;) {
int j = i;
for (; j + 1 < m && meetings[j + 1][2] == meetings[i][2]; ++j)
;
for (; j + 1 < m && meetings[j + 1][2] == meetings[i][2];) {
++j;
}
unordered_map<int, vector<int>> g;
unordered_set<int> s;
for (int k = i; k <= j; ++k) {
Expand All @@ -201,9 +217,11 @@ public:
s.insert(y);
}
queue<int> q;
for (int u : s)
if (vis[u])
for (int u : s) {
if (vis[u]) {
q.push(u);
}
}
while (!q.empty()) {
int u = q.front();
q.pop();
Expand All @@ -217,9 +235,11 @@ public:
i = j + 1;
}
vector<int> ans;
for (int i = 0; i < n; ++i)
if (vis[i])
for (int i = 0; i < n; ++i) {
if (vis[i]) {
ans.push_back(i);
}
}
return ans;
}
};
Expand Down Expand Up @@ -278,48 +298,57 @@ func findAllPeople(n int, meetings [][]int, firstPerson int) []int {

```ts
function findAllPeople(n: number, meetings: number[][], firstPerson: number): number[] {
let parent: Array<number> = Array.from({ length: n + 1 }, (v, i) => i);
parent[firstPerson] = 0;
const vis: boolean[] = Array(n).fill(false);
vis[0] = true;
vis[firstPerson] = true;

function findParent(index: number): number {
if (parent[index] != index) parent[index] = findParent(parent[index]);
return parent[index];
}
meetings.sort((x, y) => x[2] - y[2]);

let map = new Map<number, Array<Array<number>>>();
for (let meeting of meetings) {
const time = meeting[2];
let members: Array<Array<number>> = map.get(time) || new Array();
members.push(meeting);
map.set(time, members);
}
const times = [...map.keys()].sort((a, b) => a - b);
for (let time of times) {
// round 1
for (let meeting of map.get(time)) {
let [a, b] = meeting;
if (!parent[findParent(a)] || !parent[findParent(b)]) {
parent[findParent(a)] = 0;
parent[findParent(b)] = 0;
for (let i = 0, m = meetings.length; i < m; ) {
let j = i;
while (j + 1 < m && meetings[j + 1][2] === meetings[i][2]) {
++j;
}

const g = new Map<number, number[]>();
const s = new Set<number>();

for (let k = i; k <= j; ++k) {
const x = meetings[k][0];
const y = meetings[k][1];

if (!g.has(x)) g.set(x, []);
if (!g.has(y)) g.set(y, []);

g.get(x)!.push(y);
g.get(y)!.push(x);

s.add(x);
s.add(y);
}

const q: number[] = [];
for (const u of s) {
if (vis[u]) {
q.push(u);
}
parent[findParent(a)] = parent[findParent(b)];
}
// round 2
for (let meeting of map.get(time)) {
let [a, b] = meeting;
if (!parent[findParent(a)] || !parent[findParent(b)]) {
parent[findParent(a)] = 0;
parent[findParent(b)] = 0;
} else {
parent[a] = a;
parent[b] = b;

for (const u of q) {
for (const v of g.get(u)!) {
if (!vis[v]) {
vis[v] = true;
q.push(v);
}
}
}

i = j + 1;
}

let ans = new Array<number>();
for (let i = 0; i <= n; i++) {
if (!parent[findParent(i)]) {
const ans: number[] = [];
for (let i = 0; i < n; ++i) {
if (vis[i]) {
ans.push(i);
}
}
Expand Down
117 changes: 73 additions & 44 deletions solution/2000-2099/2092.Find All People With Secret/README_EN.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,21 @@ Thus, people 0, 1, 2, 3, and 4 know the secret after all the meetings.

<!-- solution:start -->

### Solution 1
### Solution 1: Simulation + Graph Traversal

The core idea of this problem is to find all people who eventually know the secret by simulating the propagation process through meetings. We can treat each meeting as an edge in an undirected graph, where each participant is a node in the graph, and the meeting time is the "timestamp" of the edge connecting the nodes. At each time point, we traverse all meetings and use Breadth-First Search (BFS) to simulate the propagation of the secret.

We create a boolean array $\textit{vis}$ to record whether each person knows the secret. Initially, $\textit{vis}[0] = \text{true}$ and $\textit{vis}[\textit{firstPerson}] = \text{true}$, indicating that person 0 and $\textit{firstPerson}$ already know the secret.

We first sort the meetings by time to ensure that we process meetings in the correct order during each traversal.

Next, we process each group of meetings at the same time. For each group of meetings at the same time (i.e., $\textit{meetings}[i][2] = \textit{meetings}[i+1][2]$), we treat them as events occurring at the same moment. For each meeting, we record the relationships between participants and add these participants to a set.

Then, we use BFS to propagate the secret. For all participants at the current time point, if any of them already know the secret, we will traverse the adjacent nodes of that participant (i.e., other participants in the meeting) through BFS and mark them as knowing the secret. This process continues to propagate until all people who can know the secret at this meeting are updated.

When all meetings are processed, we traverse the $\textit{vis}$ array, add the IDs of all people who know the secret to the result list, and return it.

The time complexity is $O(m \times \log m + n)$, and the space complexity is $O(n)$, where $m$ and $n$ are the number of meetings and the number of experts, respectively.

<!-- tabs:start -->

Expand Down Expand Up @@ -136,8 +150,9 @@ class Solution {
Arrays.sort(meetings, Comparator.comparingInt(a -> a[2]));
for (int i = 0; i < m;) {
int j = i;
for (; j + 1 < m && meetings[j + 1][2] == meetings[i][2]; ++j)
;
for (; j + 1 < m && meetings[j + 1][2] == meetings[i][2];) {
++j;
}
Map<Integer, List<Integer>> g = new HashMap<>();
Set<Integer> s = new HashSet<>();
for (int k = i; k <= j; ++k) {
Expand All @@ -155,7 +170,7 @@ class Solution {
}
while (!q.isEmpty()) {
int u = q.poll();
for (int v : g.getOrDefault(u, Collections.emptyList())) {
for (int v : g.getOrDefault(u, List.of())) {
if (!vis[v]) {
vis[v] = true;
q.offer(v);
Expand Down Expand Up @@ -188,8 +203,9 @@ public:
});
for (int i = 0, m = meetings.size(); i < m;) {
int j = i;
for (; j + 1 < m && meetings[j + 1][2] == meetings[i][2]; ++j)
;
for (; j + 1 < m && meetings[j + 1][2] == meetings[i][2];) {
++j;
}
unordered_map<int, vector<int>> g;
unordered_set<int> s;
for (int k = i; k <= j; ++k) {
Expand All @@ -200,9 +216,11 @@ public:
s.insert(y);
}
queue<int> q;
for (int u : s)
if (vis[u])
for (int u : s) {
if (vis[u]) {
q.push(u);
}
}
while (!q.empty()) {
int u = q.front();
q.pop();
Expand All @@ -216,9 +234,11 @@ public:
i = j + 1;
}
vector<int> ans;
for (int i = 0; i < n; ++i)
if (vis[i])
for (int i = 0; i < n; ++i) {
if (vis[i]) {
ans.push_back(i);
}
}
return ans;
}
};
Expand Down Expand Up @@ -277,48 +297,57 @@ func findAllPeople(n int, meetings [][]int, firstPerson int) []int {

```ts
function findAllPeople(n: number, meetings: number[][], firstPerson: number): number[] {
let parent: Array<number> = Array.from({ length: n + 1 }, (v, i) => i);
parent[firstPerson] = 0;
const vis: boolean[] = Array(n).fill(false);
vis[0] = true;
vis[firstPerson] = true;

function findParent(index: number): number {
if (parent[index] != index) parent[index] = findParent(parent[index]);
return parent[index];
}
meetings.sort((x, y) => x[2] - y[2]);

let map = new Map<number, Array<Array<number>>>();
for (let meeting of meetings) {
const time = meeting[2];
let members: Array<Array<number>> = map.get(time) || new Array();
members.push(meeting);
map.set(time, members);
}
const times = [...map.keys()].sort((a, b) => a - b);
for (let time of times) {
// round 1
for (let meeting of map.get(time)) {
let [a, b] = meeting;
if (!parent[findParent(a)] || !parent[findParent(b)]) {
parent[findParent(a)] = 0;
parent[findParent(b)] = 0;
for (let i = 0, m = meetings.length; i < m; ) {
let j = i;
while (j + 1 < m && meetings[j + 1][2] === meetings[i][2]) {
++j;
}

const g = new Map<number, number[]>();
const s = new Set<number>();

for (let k = i; k <= j; ++k) {
const x = meetings[k][0];
const y = meetings[k][1];

if (!g.has(x)) g.set(x, []);
if (!g.has(y)) g.set(y, []);

g.get(x)!.push(y);
g.get(y)!.push(x);

s.add(x);
s.add(y);
}

const q: number[] = [];
for (const u of s) {
if (vis[u]) {
q.push(u);
}
parent[findParent(a)] = parent[findParent(b)];
}
// round 2
for (let meeting of map.get(time)) {
let [a, b] = meeting;
if (!parent[findParent(a)] || !parent[findParent(b)]) {
parent[findParent(a)] = 0;
parent[findParent(b)] = 0;
} else {
parent[a] = a;
parent[b] = b;

for (const u of q) {
for (const v of g.get(u)!) {
if (!vis[v]) {
vis[v] = true;
q.push(v);
}
}
}

i = j + 1;
}

let ans = new Array<number>();
for (let i = 0; i <= n; i++) {
if (!parent[findParent(i)]) {
const ans: number[] = [];
for (let i = 0; i < n; ++i) {
if (vis[i]) {
ans.push(i);
}
}
Expand Down
19 changes: 12 additions & 7 deletions solution/2000-2099/2092.Find All People With Secret/Solution.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ class Solution {
});
for (int i = 0, m = meetings.size(); i < m;) {
int j = i;
for (; j + 1 < m && meetings[j + 1][2] == meetings[i][2]; ++j)
;
for (; j + 1 < m && meetings[j + 1][2] == meetings[i][2];) {
++j;
}
unordered_map<int, vector<int>> g;
unordered_set<int> s;
for (int k = i; k <= j; ++k) {
Expand All @@ -20,9 +21,11 @@ class Solution {
s.insert(y);
}
queue<int> q;
for (int u : s)
if (vis[u])
for (int u : s) {
if (vis[u]) {
q.push(u);
}
}
while (!q.empty()) {
int u = q.front();
q.pop();
Expand All @@ -36,9 +39,11 @@ class Solution {
i = j + 1;
}
vector<int> ans;
for (int i = 0; i < n; ++i)
if (vis[i])
for (int i = 0; i < n; ++i) {
if (vis[i]) {
ans.push_back(i);
}
}
return ans;
}
};
};
Loading