Skip to content

Commit 2a56f9f

Browse files
committed
Create: 2421-number-of-good-paths.rs / .ts / .js / .go
1 parent ee7a3bc commit 2a56f9f

4 files changed

+413
-0
lines changed

go/2421-number-of-good-paths.go

+108
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
package main
2+
3+
import "sort"
4+
5+
func main() {
6+
7+
}
8+
9+
type UnionFind struct {
10+
parent []int
11+
rank []int
12+
}
13+
14+
func Constructor(n int) UnionFind {
15+
parent := make([]int, n)
16+
rank := make([]int, n)
17+
18+
for i := 0; i < n; i++ {
19+
parent[i] = i
20+
rank[i] = 1
21+
}
22+
return UnionFind{
23+
parent, rank,
24+
}
25+
}
26+
27+
func (u *UnionFind) find(i int) int {
28+
for i != u.parent[i] {
29+
u.parent[i] = u.parent[u.parent[i]]
30+
i = u.parent[i]
31+
}
32+
33+
return i
34+
}
35+
36+
func (u *UnionFind) union(a, b int) bool {
37+
aRoot, bRoot := u.find(a), u.find(b)
38+
39+
if aRoot == bRoot {
40+
return false
41+
}
42+
43+
if u.rank[aRoot] < u.rank[bRoot] {
44+
u.parent[aRoot] = bRoot
45+
u.rank[bRoot] += u.rank[aRoot]
46+
} else {
47+
u.parent[bRoot] = aRoot
48+
u.rank[aRoot] += u.rank[bRoot]
49+
}
50+
51+
return true
52+
}
53+
54+
func getAdjList(edges [][]int) map[int][]int {
55+
adj := make(map[int][]int)
56+
57+
for _, edge := range edges {
58+
a, b := edge[0], edge[1]
59+
60+
adj[a] = append(adj[a], b)
61+
adj[b] = append(adj[b], a)
62+
}
63+
64+
return adj
65+
}
66+
67+
func getValToIndex(vals []int) map[int][]int {
68+
valToIndex := make(map[int][]int)
69+
70+
for i, val := range vals {
71+
valToIndex[val] = append(valToIndex[val], i)
72+
}
73+
74+
return valToIndex
75+
}
76+
77+
func numberOfGoodPaths(vals []int, edges [][]int) int {
78+
adj := getAdjList(edges)
79+
valToIndex := getValToIndex(vals)
80+
81+
res := 0
82+
uf := Constructor(len(vals))
83+
84+
keys := make([]int, 0, len(valToIndex))
85+
for k := range valToIndex {
86+
keys = append(keys, k)
87+
}
88+
sort.Ints(keys)
89+
90+
for _, val := range keys {
91+
for _, i := range valToIndex[val] {
92+
for _, nei := range adj[i] {
93+
if vals[nei] <= vals[i] {
94+
uf.union(nei, i)
95+
}
96+
}
97+
}
98+
99+
count := make(map[int]int)
100+
101+
for _, i := range valToIndex[val] {
102+
count[uf.find(i)] += 1
103+
res += count[uf.find(i)]
104+
}
105+
}
106+
107+
return res
108+
}
+113
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
class UnionFind {
2+
constructor(n) {
3+
this.parent = new Array(n).fill(0).map((_, i) => i);
4+
this.rank = new Array(n).fill(0);
5+
}
6+
7+
/**
8+
*
9+
* @param {number} i
10+
* @returns {number}
11+
*/
12+
find(i) {
13+
while (i !== this.parent[i]) {
14+
this.parent[i] = this.parent[this.parent[i]];
15+
i = this.parent[i];
16+
}
17+
return i;
18+
}
19+
20+
/**
21+
*
22+
* @param {number} a
23+
* @param {number} b
24+
* @returns {boolean}
25+
*/
26+
union(a, b) {
27+
let [aRoot, bRoot] = [this.find(a), this.find(b)];
28+
29+
if (aRoot == bRoot) return false;
30+
31+
if (this.rank[aRoot] < this.rank[bRoot]) {
32+
this.parent[aRoot] = bRoot;
33+
this.rank[bRoot] += this.rank[aRoot];
34+
} else {
35+
this.parent[bRoot] = aRoot;
36+
this.rank[aRoot] += this.rank[bRoot];
37+
}
38+
39+
return true;
40+
}
41+
}
42+
43+
/**
44+
*
45+
* @param {number[number[]]} edges
46+
* @returns {Map<number, number[]>}
47+
*/
48+
const getAdjList = (edges) => {
49+
let adj = new Map();
50+
51+
for (e of edges) {
52+
let [a, b] = [e[0], e[1]];
53+
54+
let [adjA, adjB] = [adj.get(a) || [], adj.get(b) || []];
55+
56+
adjA.push(b);
57+
adjB.push(a);
58+
59+
adj.set(a, adjA);
60+
adj.set(b, adjB);
61+
}
62+
63+
return adj;
64+
};
65+
66+
const getValToIndex = (vals) => {
67+
let valToIndex = new Map();
68+
69+
for (i in vals) {
70+
let val = vals[i];
71+
let arr = valToIndex.get(val) || [];
72+
arr.push(+i);
73+
valToIndex.set(val, arr);
74+
}
75+
76+
return valToIndex;
77+
};
78+
79+
/**
80+
*
81+
* @param {number[]} vals
82+
* @param {number[number[]]} edges
83+
* @returns {number}
84+
*/
85+
const numberOfGoodPaths = (vals, edges) => {
86+
let adj = getAdjList(edges);
87+
let valToIndex = getValToIndex(vals);
88+
89+
let res = 0;
90+
let uf = new UnionFind(vals.length);
91+
92+
let keys = Array.from(valToIndex.keys());
93+
keys.sort((a, b) => a - b);
94+
95+
for (let val of keys) {
96+
for (let i of valToIndex.get(val)) {
97+
for (let nei of adj.get(i) || []) {
98+
if (vals[nei] <= vals[i]) {
99+
uf.union(nei, i);
100+
}
101+
}
102+
}
103+
let count = new Map();
104+
105+
for (let i of valToIndex.get(val)) {
106+
let c = count.get(uf.find(i)) || 0;
107+
count.set(uf.find(i), c + 1);
108+
res += count.get(uf.find(i));
109+
}
110+
}
111+
112+
return res;
113+
};

rust/2421-number-of-good-paths.rs

+97
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
use std::{cmp::Ordering, collections::HashMap};
2+
3+
struct UnionFind {
4+
parent: Vec<usize>,
5+
rank: Vec<i32>,
6+
}
7+
8+
impl UnionFind {
9+
fn new(n: usize) -> Self {
10+
UnionFind {
11+
parent: (0..n).collect(),
12+
rank: vec![0; n],
13+
}
14+
}
15+
16+
fn find(&mut self, mut i: usize) -> usize {
17+
while i != self.parent[i] {
18+
self.parent[i] = self.parent[self.parent[i]];
19+
i = self.parent[i];
20+
}
21+
i
22+
}
23+
24+
fn union(&mut self, a: usize, b: usize) -> bool {
25+
let a_root = self.find(a);
26+
let b_root = self.find(b);
27+
28+
if a_root == b_root {
29+
return false;
30+
}
31+
match self.rank[a_root].cmp(&self.rank[b_root]) {
32+
Ordering::Less => {
33+
self.parent[a_root] = b_root;
34+
self.rank[b_root] += self.rank[a_root];
35+
}
36+
_ => {
37+
self.parent[b_root] = a_root;
38+
self.rank[a_root] = self.rank[b_root];
39+
}
40+
}
41+
true
42+
}
43+
}
44+
45+
impl Solution {
46+
pub fn number_of_good_paths(vals: Vec<i32>, edges: Vec<Vec<i32>>) -> i32 {
47+
let adj = Self::create_adj_list(&edges);
48+
let val_to_index = Self::create_val_to_index(&vals);
49+
50+
let mut res = 0;
51+
let mut uf = UnionFind::new(vals.len());
52+
53+
let mut keys: Vec<i32> = val_to_index.keys().cloned().collect();
54+
keys.sort();
55+
56+
for val in keys {
57+
for i in val_to_index.get(&val).unwrap_or(&vec![]) {
58+
for nei in adj.get(&(*i as i32)).unwrap_or(&vec![]) {
59+
if vals[*nei as usize] <= vals[*i] {
60+
uf.union(*nei as usize, *i);
61+
}
62+
}
63+
}
64+
let mut count = HashMap::new();
65+
for i in val_to_index.get(&val).unwrap() {
66+
*count.entry(uf.find(*i)).or_insert(0) += 1;
67+
res += count.get(&uf.find(*i)).unwrap();
68+
}
69+
}
70+
71+
res
72+
}
73+
74+
pub fn create_adj_list(edges: &Vec<Vec<i32>>) -> HashMap<i32, Vec<i32>> {
75+
let mut adj = HashMap::new();
76+
77+
for edge in edges {
78+
let a = edge[0];
79+
let b = edge[1];
80+
81+
adj.entry(a).or_insert(vec![]).push(b);
82+
adj.entry(b).or_insert(vec![]).push(a);
83+
}
84+
85+
adj
86+
}
87+
88+
pub fn create_val_to_index(vals: &Vec<i32>) -> HashMap<i32, Vec<usize>> {
89+
let mut val_to_index = HashMap::new();
90+
91+
for (i, val) in vals.iter().enumerate() {
92+
val_to_index.entry(*val).or_insert(vec![]).push(i);
93+
}
94+
95+
val_to_index
96+
}
97+
}

0 commit comments

Comments
 (0)