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
108 changes: 108 additions & 0 deletions go/2421-number-of-good-paths.go
Original file line number Diff line number Diff line change
@@ -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
}
113 changes: 113 additions & 0 deletions javascript/2421-number-of-good-paths.js
Original file line number Diff line number Diff line change
@@ -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<number, number[]>}
*/
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;
};
97 changes: 97 additions & 0 deletions rust/2421-number-of-good-paths.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
use std::{cmp::Ordering, collections::HashMap};

struct UnionFind {
parent: Vec<usize>,
rank: Vec<i32>,
}

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<i32>, edges: Vec<Vec<i32>>) -> 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<i32> = 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<Vec<i32>>) -> HashMap<i32, Vec<i32>> {
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<i32>) -> HashMap<i32, Vec<usize>> {
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
}
}
Loading