Skip to content

Latest commit

 

History

History
85 lines (72 loc) · 2.5 KB

leetcode_2421.md

File metadata and controls

85 lines (72 loc) · 2.5 KB

LeetCode Problems

2421. Number of Good Paths

class Solution {
    class UnionFind(size: Int) {
        private val parent: IntArray = IntArray(size, { it })
        private val rank: IntArray = IntArray(size)
        
        fun find(n: Int): Int {
            if (parent[n] != n) {
                parent[n] = find(parent[n])
            }
            return parent[n]
        }
        fun union(n1: Int, n2: Int) {
            val p1 = find(n1)
            val p2 = find(n2)
            if (p1 == p2) return
            when {
                rank[p1] > rank[p2] -> parent[p2] = p1
                rank[p1] < rank[p2] -> parent[p1] = p2
                else -> {
                    parent[p2] = p1
                    rank[p1]++
                 }
            }
        }
        
    }


    fun numberOfGoodPaths(vals: IntArray, edges: Array<IntArray>): Int {
        val size = vals.size
        val unionFind = UnionFind(size)
        val graph = Array<MutableList<Int>>(vals.size, { mutableListOf() })
        val valueMap = mutableMapOf<Int, MutableList<Int>>()
        for (i in 0 until size) {
            if (!valueMap.containsKey(vals[i])) valueMap[vals[i]] = mutableListOf()
            valueMap[vals[i]]!!.add(i)
        }
        edges.forEach { edge ->
            val a = edge[0]
            val b = edge[1]
            if (vals[a] >= vals[b]) graph[a].add(b)
            if (vals[a] <= vals[b]) graph[b].add(a)
        }

        var result = 0
        valueMap.keys.sorted().forEach { key ->
            val valNode = valueMap[key]!!
            // iterate nodes with current value
            // build disjoint-set with each neighbors
            valNode.forEach { node ->
                graph[node].forEach { neighbor ->
                    unionFind.union(node, neighbor)
                }
            }
            // get nodes' possible-group size. 
            val groupSize = mutableMapOf<Int, Int>()
            valNode.forEach { node ->
                val groupId = unionFind.find(node)
                if (!groupSize.containsKey(groupId)) groupSize[groupId] = 0
                groupSize[groupId] = groupSize[groupId]!! + 1
            }
            // result is each groupSize's nC2
            groupSize.forEach { _, size -> 
                result += size * (size + 1) / 2 
            }
        }
        return result
    }
}