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
104 changes: 89 additions & 15 deletions solution/1700-1799/1733.Minimum Number of People to Teach/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ tags:

对于每个好友关系,如果两个人掌握的语言集合不相交,则需要教一门语言,使得两个人可以相互沟通,我们将这些人放入一个哈希集合 $s$ 中。

然后在这个集合 $s$ 中,统计每种语言掌握的人数,获取最大的人数,我们记为 $mx$,那么答案就是 `len(s) - mx`
然后在这个集合 $s$ 中,统计每种语言掌握的人数,获取最大的人数,我们记为 $mx$,那么答案就是 $|s| - mx$。其中 $|s|$ 表示集合 $s$ 的大小

时间复杂度 $O(m^2 \times k)$。其中 $m$ 为语言的数量,而 $k$ 为好友关系的数量。

Expand All @@ -90,7 +90,7 @@ class Solution:
def minimumTeachings(
self, n: int, languages: List[List[int]], friendships: List[List[int]]
) -> int:
def check(u, v):
def check(u: int, v: int) -> bool:
for x in languages[u - 1]:
for y in languages[v - 1]:
if x == y:
Expand Down Expand Up @@ -158,9 +158,19 @@ class Solution {
public:
int minimumTeachings(int n, vector<vector<int>>& languages, vector<vector<int>>& friendships) {
unordered_set<int> s;
auto check = [&](int u, int v) {
for (int x : languages[u - 1]) {
for (int y : languages[v - 1]) {
if (x == y) {
return true;
}
}
}
return false;
};
for (auto& e : friendships) {
int u = e[0], v = e[1];
if (!check(u, v, languages)) {
if (!check(u, v)) {
s.insert(u);
s.insert(v);
}
Expand All @@ -174,18 +184,7 @@ public:
++cnt[l];
}
}
return s.size() - *max_element(cnt.begin(), cnt.end());
}

bool check(int u, int v, vector<vector<int>>& languages) {
for (int x : languages[u - 1]) {
for (int y : languages[v - 1]) {
if (x == y) {
return true;
}
}
}
return false;
return s.size() - ranges::max(cnt);
}
};
```
Expand Down Expand Up @@ -224,6 +223,81 @@ func minimumTeachings(n int, languages [][]int, friendships [][]int) int {
}
```

#### TypeScript

```ts
function minimumTeachings(n: number, languages: number[][], friendships: number[][]): number {
function check(u: number, v: number): boolean {
for (const x of languages[u - 1]) {
for (const y of languages[v - 1]) {
if (x === y) {
return true;
}
}
}
return false;
}

const s = new Set<number>();
for (const [u, v] of friendships) {
if (!check(u, v)) {
s.add(u);
s.add(v);
}
}

const cnt = new Map<number, number>();
for (const u of s) {
for (const l of languages[u - 1]) {
cnt.set(l, (cnt.get(l) || 0) + 1);
}
}

return s.size - Math.max(0, ...cnt.values());
}
```

#### Rust

```rust
use std::collections::{HashSet, HashMap};

impl Solution {
pub fn minimum_teachings(n: i32, languages: Vec<Vec<i32>>, friendships: Vec<Vec<i32>>) -> i32 {
fn check(u: usize, v: usize, languages: &Vec<Vec<i32>>) -> bool {
for &x in &languages[u - 1] {
for &y in &languages[v - 1] {
if x == y {
return true;
}
}
}
false
}

let mut s: HashSet<usize> = HashSet::new();
for edge in friendships.iter() {
let u = edge[0] as usize;
let v = edge[1] as usize;
if !check(u, v, &languages) {
s.insert(u);
s.insert(v);
}
}

let mut cnt: HashMap<i32, i32> = HashMap::new();
for &u in s.iter() {
for &l in &languages[u - 1] {
*cnt.entry(l).or_insert(0) += 1;
}
}

let mx = cnt.values().cloned().max().unwrap_or(0);
(s.len() as i32) - mx
}
}
```

<!-- tabs:end -->

<!-- solution:end -->
Expand Down
106 changes: 90 additions & 16 deletions solution/1700-1799/1733.Minimum Number of People to Teach/README_EN.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,9 @@ Note that friendships are not transitive, meaning if <code>x</code> is a friend

### Solution 1: Simulation + Statistics

For each friendship, if the sets of languages known by the two people do not intersect, then a language needs to be taught so that the two people can communicate with each other. We put these people into a hash set $s$.
For each friendship, if the sets of languages known by the two people do not intersect, we need to teach one language so that they can communicate. We add these people to a hash set $s$.

Then in this set $s$, we count the number of people who know each language, and get the maximum number, which we denote as $mx$. So the answer is `len(s) - mx`.
Then, for each language, we count how many people in set $s$ know that language and find the maximum count, denoted as $mx$. The answer is $|s| - mx$, where $|s|$ is the size of set $s$.

The time complexity is $O(m^2 \times k)$. Here, $m$ is the number of languages, and $k$ is the number of friendships.

Expand All @@ -87,7 +87,7 @@ class Solution:
def minimumTeachings(
self, n: int, languages: List[List[int]], friendships: List[List[int]]
) -> int:
def check(u, v):
def check(u: int, v: int) -> bool:
for x in languages[u - 1]:
for y in languages[v - 1]:
if x == y:
Expand Down Expand Up @@ -155,9 +155,19 @@ class Solution {
public:
int minimumTeachings(int n, vector<vector<int>>& languages, vector<vector<int>>& friendships) {
unordered_set<int> s;
auto check = [&](int u, int v) {
for (int x : languages[u - 1]) {
for (int y : languages[v - 1]) {
if (x == y) {
return true;
}
}
}
return false;
};
for (auto& e : friendships) {
int u = e[0], v = e[1];
if (!check(u, v, languages)) {
if (!check(u, v)) {
s.insert(u);
s.insert(v);
}
Expand All @@ -171,18 +181,7 @@ public:
++cnt[l];
}
}
return s.size() - *max_element(cnt.begin(), cnt.end());
}

bool check(int u, int v, vector<vector<int>>& languages) {
for (int x : languages[u - 1]) {
for (int y : languages[v - 1]) {
if (x == y) {
return true;
}
}
}
return false;
return s.size() - ranges::max(cnt);
}
};
```
Expand Down Expand Up @@ -221,6 +220,81 @@ func minimumTeachings(n int, languages [][]int, friendships [][]int) int {
}
```

#### TypeScript

```ts
function minimumTeachings(n: number, languages: number[][], friendships: number[][]): number {
function check(u: number, v: number): boolean {
for (const x of languages[u - 1]) {
for (const y of languages[v - 1]) {
if (x === y) {
return true;
}
}
}
return false;
}

const s = new Set<number>();
for (const [u, v] of friendships) {
if (!check(u, v)) {
s.add(u);
s.add(v);
}
}

const cnt = new Map<number, number>();
for (const u of s) {
for (const l of languages[u - 1]) {
cnt.set(l, (cnt.get(l) || 0) + 1);
}
}

return s.size - Math.max(0, ...cnt.values());
}
```

#### Rust

```rust
use std::collections::{HashSet, HashMap};

impl Solution {
pub fn minimum_teachings(n: i32, languages: Vec<Vec<i32>>, friendships: Vec<Vec<i32>>) -> i32 {
fn check(u: usize, v: usize, languages: &Vec<Vec<i32>>) -> bool {
for &x in &languages[u - 1] {
for &y in &languages[v - 1] {
if x == y {
return true;
}
}
}
false
}

let mut s: HashSet<usize> = HashSet::new();
for edge in friendships.iter() {
let u = edge[0] as usize;
let v = edge[1] as usize;
if !check(u, v, &languages) {
s.insert(u);
s.insert(v);
}
}

let mut cnt: HashMap<i32, i32> = HashMap::new();
for &u in s.iter() {
for &l in &languages[u - 1] {
*cnt.entry(l).or_insert(0) += 1;
}
}

let mx = cnt.values().cloned().max().unwrap_or(0);
(s.len() as i32) - mx
}
}
```

<!-- tabs:end -->

<!-- solution:end -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,19 @@ class Solution {
public:
int minimumTeachings(int n, vector<vector<int>>& languages, vector<vector<int>>& friendships) {
unordered_set<int> s;
auto check = [&](int u, int v) {
for (int x : languages[u - 1]) {
for (int y : languages[v - 1]) {
if (x == y) {
return true;
}
}
}
return false;
};
for (auto& e : friendships) {
int u = e[0], v = e[1];
if (!check(u, v, languages)) {
if (!check(u, v)) {
s.insert(u);
s.insert(v);
}
Expand All @@ -18,17 +28,6 @@ class Solution {
++cnt[l];
}
}
return s.size() - *max_element(cnt.begin(), cnt.end());
}

bool check(int u, int v, vector<vector<int>>& languages) {
for (int x : languages[u - 1]) {
for (int y : languages[v - 1]) {
if (x == y) {
return true;
}
}
}
return false;
return s.size() - ranges::max(cnt);
}
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ class Solution:
def minimumTeachings(
self, n: int, languages: List[List[int]], friendships: List[List[int]]
) -> int:
def check(u, v):
def check(u: int, v: int) -> bool:
for x in languages[u - 1]:
for y in languages[v - 1]:
if x == y:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
use std::collections::{HashMap, HashSet};

impl Solution {
pub fn minimum_teachings(n: i32, languages: Vec<Vec<i32>>, friendships: Vec<Vec<i32>>) -> i32 {
fn check(u: usize, v: usize, languages: &Vec<Vec<i32>>) -> bool {
for &x in &languages[u - 1] {
for &y in &languages[v - 1] {
if x == y {
return true;
}
}
}
false
}

let mut s: HashSet<usize> = HashSet::new();
for edge in friendships.iter() {
let u = edge[0] as usize;
let v = edge[1] as usize;
if !check(u, v, &languages) {
s.insert(u);
s.insert(v);
}
}

let mut cnt: HashMap<i32, i32> = HashMap::new();
for &u in s.iter() {
for &l in &languages[u - 1] {
*cnt.entry(l).or_insert(0) += 1;
}
}

let mx = cnt.values().cloned().max().unwrap_or(0);
(s.len() as i32) - mx
}
}
Loading