From 2a56f9f0df1e39c898b9d7a1ee9d47b63975bfa7 Mon Sep 17 00:00:00 2001 From: AkifhanIlgaz Date: Sun, 15 Jan 2023 22:22:24 +0300 Subject: [PATCH] Create: 2421-number-of-good-paths.rs / .ts / .js / .go --- go/2421-number-of-good-paths.go | 108 ++++++++++++++++++++++ javascript/2421-number-of-good-paths.js | 113 ++++++++++++++++++++++++ rust/2421-number-of-good-paths.rs | 97 ++++++++++++++++++++ typescript/2421-number-of-good-paths.ts | 95 ++++++++++++++++++++ 4 files changed, 413 insertions(+) create mode 100644 go/2421-number-of-good-paths.go create mode 100644 javascript/2421-number-of-good-paths.js create mode 100644 rust/2421-number-of-good-paths.rs create mode 100644 typescript/2421-number-of-good-paths.ts diff --git a/go/2421-number-of-good-paths.go b/go/2421-number-of-good-paths.go new file mode 100644 index 000000000..d5387854d --- /dev/null +++ b/go/2421-number-of-good-paths.go @@ -0,0 +1,108 @@ +package main + +import "sort" + +func main() { + +} + +type UnionFind struct { + parent []int + rank []int +} + +func Constructor(n int) UnionFind { + parent := make([]int, n) + rank := make([]int, n) + + for i := 0; i < n; i++ { + parent[i] = i + rank[i] = 1 + } + return UnionFind{ + parent, rank, + } +} + +func (u *UnionFind) find(i int) int { + for i != u.parent[i] { + u.parent[i] = u.parent[u.parent[i]] + i = u.parent[i] + } + + return i +} + +func (u *UnionFind) union(a, b int) bool { + aRoot, bRoot := u.find(a), u.find(b) + + if aRoot == bRoot { + return false + } + + if u.rank[aRoot] < u.rank[bRoot] { + u.parent[aRoot] = bRoot + u.rank[bRoot] += u.rank[aRoot] + } else { + u.parent[bRoot] = aRoot + u.rank[aRoot] += u.rank[bRoot] + } + + return true +} + +func getAdjList(edges [][]int) map[int][]int { + adj := make(map[int][]int) + + for _, edge := range edges { + a, b := edge[0], edge[1] + + adj[a] = append(adj[a], b) + adj[b] = append(adj[b], a) + } + + return adj +} + +func getValToIndex(vals []int) map[int][]int { + valToIndex := make(map[int][]int) + + for i, val := range vals { + valToIndex[val] = append(valToIndex[val], i) + } + + return valToIndex +} + +func numberOfGoodPaths(vals []int, edges [][]int) int { + adj := getAdjList(edges) + valToIndex := getValToIndex(vals) + + res := 0 + uf := Constructor(len(vals)) + + keys := make([]int, 0, len(valToIndex)) + for k := range valToIndex { + keys = append(keys, k) + } + sort.Ints(keys) + + for _, val := range keys { + for _, i := range valToIndex[val] { + for _, nei := range adj[i] { + if vals[nei] <= vals[i] { + uf.union(nei, i) + } + } + } + + count := make(map[int]int) + + for _, i := range valToIndex[val] { + count[uf.find(i)] += 1 + res += count[uf.find(i)] + } + } + + return res +} \ No newline at end of file diff --git a/javascript/2421-number-of-good-paths.js b/javascript/2421-number-of-good-paths.js new file mode 100644 index 000000000..041acf7e1 --- /dev/null +++ b/javascript/2421-number-of-good-paths.js @@ -0,0 +1,113 @@ +class UnionFind { + constructor(n) { + this.parent = new Array(n).fill(0).map((_, i) => i); + this.rank = new Array(n).fill(0); + } + + /** + * + * @param {number} i + * @returns {number} + */ + find(i) { + while (i !== this.parent[i]) { + this.parent[i] = this.parent[this.parent[i]]; + i = this.parent[i]; + } + return i; + } + + /** + * + * @param {number} a + * @param {number} b + * @returns {boolean} + */ + union(a, b) { + let [aRoot, bRoot] = [this.find(a), this.find(b)]; + + if (aRoot == bRoot) return false; + + if (this.rank[aRoot] < this.rank[bRoot]) { + this.parent[aRoot] = bRoot; + this.rank[bRoot] += this.rank[aRoot]; + } else { + this.parent[bRoot] = aRoot; + this.rank[aRoot] += this.rank[bRoot]; + } + + return true; + } +} + +/** + * + * @param {number[number[]]} edges + * @returns {Map} + */ +const getAdjList = (edges) => { + let adj = new Map(); + + for (e of edges) { + let [a, b] = [e[0], e[1]]; + + let [adjA, adjB] = [adj.get(a) || [], adj.get(b) || []]; + + adjA.push(b); + adjB.push(a); + + adj.set(a, adjA); + adj.set(b, adjB); + } + + return adj; +}; + +const getValToIndex = (vals) => { + let valToIndex = new Map(); + + for (i in vals) { + let val = vals[i]; + let arr = valToIndex.get(val) || []; + arr.push(+i); + valToIndex.set(val, arr); + } + + return valToIndex; +}; + +/** + * + * @param {number[]} vals + * @param {number[number[]]} edges + * @returns {number} + */ +const numberOfGoodPaths = (vals, edges) => { + let adj = getAdjList(edges); + let valToIndex = getValToIndex(vals); + + let res = 0; + let uf = new UnionFind(vals.length); + + let keys = Array.from(valToIndex.keys()); + keys.sort((a, b) => a - b); + + for (let val of keys) { + for (let i of valToIndex.get(val)) { + for (let nei of adj.get(i) || []) { + if (vals[nei] <= vals[i]) { + uf.union(nei, i); + } + } + } + let count = new Map(); + + for (let i of valToIndex.get(val)) { + let c = count.get(uf.find(i)) || 0; + count.set(uf.find(i), c + 1); + res += count.get(uf.find(i)); + } + } + + return res; +}; diff --git a/rust/2421-number-of-good-paths.rs b/rust/2421-number-of-good-paths.rs new file mode 100644 index 000000000..4beb736f6 --- /dev/null +++ b/rust/2421-number-of-good-paths.rs @@ -0,0 +1,97 @@ +use std::{cmp::Ordering, collections::HashMap}; + +struct UnionFind { + parent: Vec, + rank: Vec, +} + +impl UnionFind { + fn new(n: usize) -> Self { + UnionFind { + parent: (0..n).collect(), + rank: vec![0; n], + } + } + + fn find(&mut self, mut i: usize) -> usize { + while i != self.parent[i] { + self.parent[i] = self.parent[self.parent[i]]; + i = self.parent[i]; + } + i + } + + fn union(&mut self, a: usize, b: usize) -> bool { + let a_root = self.find(a); + let b_root = self.find(b); + + if a_root == b_root { + return false; + } + match self.rank[a_root].cmp(&self.rank[b_root]) { + Ordering::Less => { + self.parent[a_root] = b_root; + self.rank[b_root] += self.rank[a_root]; + } + _ => { + self.parent[b_root] = a_root; + self.rank[a_root] = self.rank[b_root]; + } + } + true + } +} + +impl Solution { + pub fn number_of_good_paths(vals: Vec, edges: Vec>) -> i32 { + let adj = Self::create_adj_list(&edges); + let val_to_index = Self::create_val_to_index(&vals); + + let mut res = 0; + let mut uf = UnionFind::new(vals.len()); + + let mut keys: Vec = val_to_index.keys().cloned().collect(); + keys.sort(); + + for val in keys { + for i in val_to_index.get(&val).unwrap_or(&vec![]) { + for nei in adj.get(&(*i as i32)).unwrap_or(&vec![]) { + if vals[*nei as usize] <= vals[*i] { + uf.union(*nei as usize, *i); + } + } + } + let mut count = HashMap::new(); + for i in val_to_index.get(&val).unwrap() { + *count.entry(uf.find(*i)).or_insert(0) += 1; + res += count.get(&uf.find(*i)).unwrap(); + } + } + + res + } + + pub fn create_adj_list(edges: &Vec>) -> HashMap> { + let mut adj = HashMap::new(); + + for edge in edges { + let a = edge[0]; + let b = edge[1]; + + adj.entry(a).or_insert(vec![]).push(b); + adj.entry(b).or_insert(vec![]).push(a); + } + + adj + } + + pub fn create_val_to_index(vals: &Vec) -> HashMap> { + let mut val_to_index = HashMap::new(); + + for (i, val) in vals.iter().enumerate() { + val_to_index.entry(*val).or_insert(vec![]).push(i); + } + + val_to_index + } +} \ No newline at end of file diff --git a/typescript/2421-number-of-good-paths.ts b/typescript/2421-number-of-good-paths.ts new file mode 100644 index 000000000..15d381581 --- /dev/null +++ b/typescript/2421-number-of-good-paths.ts @@ -0,0 +1,95 @@ +class UnionFind { + parent: number[]; + rank: number[]; + + constructor(n: number) { + this.parent = new Array(n).fill(0).map((_, i) => i); + this.rank = new Array(n).fill(0); + } + + find(i: number): number { + while (i !== this.parent[i]) { + this.parent[i] = this.parent[this.parent[i]]; + i = this.parent[i]; + } + return i; + } + + union(a: number, b: number): boolean { + let [aRoot, bRoot] = [this.find(a), this.find(b)]; + + if (aRoot == bRoot) return false; + + if (this.rank[aRoot] < this.rank[bRoot]) { + this.parent[aRoot] = bRoot; + this.rank[bRoot] += this.rank[aRoot]; + } else { + this.parent[bRoot] = aRoot; + this.rank[aRoot] += this.rank[bRoot]; + } + + return true; + } +} + +function getAdjList(edges: number[][]): Map { + let adj = new Map(); + + for (let e of edges) { + let [a, b] = [e[0], e[1]]; + + let [adjA, adjB] = [adj.get(a) || [], adj.get(b) || []]; + + adjA.push(b); + adjB.push(a); + + adj.set(a, adjA); + adj.set(b, adjB); + } + + return adj; +} + +function getValToIndex(vals: number[]): Map { + let valToIndex = new Map(); + + for (let i in vals) { + let val = vals[i]; + let arr = valToIndex.get(val) || []; + arr.push(+i); + valToIndex.set(val, arr); + } + + return valToIndex; +} + + +function numberOfGoodPaths(vals: number[], edges: number[][]): number { + let adj = getAdjList(edges); + let valToIndex = getValToIndex(vals); + + let res = 0; + let uf = new UnionFind(vals.length); + + let keys = Array.from(valToIndex.keys()); + keys.sort((a, b) => a - b); + + for (let val of keys) { + for (let i of valToIndex.get(val)!) { + for (let nei of adj.get(i) || []) { + if (vals[nei] <= vals[i]) { + uf.union(nei, i); + } + } + } + let count = new Map(); + + for (let i of valToIndex.get(val)!) { + let c = count.get(uf.find(i)) || 0; + count.set(uf.find(i), c + 1); + res += count.get(uf.find(i)); + } + } + + return res; +}