LeetCode in Kotlin

2157. Groups of Strings

Hard

You are given a 0-indexed array of strings words. Each string consists of lowercase English letters only. No letter occurs more than once in any string of words.

Two strings s1 and s2 are said to be connected if the set of letters of s2 can be obtained from the set of letters of s1 by any one of the following operations:

The array words can be divided into one or more non-intersecting groups. A string belongs to a group if any one of the following is true:

Note that the strings in words should be grouped in such a manner that a string belonging to a group cannot be connected to a string present in any other group. It can be proved that such an arrangement is always unique.

Return an array ans of size 2 where:

Example 1:

Input: words = [“a”,”b”,”ab”,”cde”]

Output: [2,3]

Explanation:

Thus, words can be divided into 2 groups [“a”,”b”,”ab”] and [“cde”]. The size of the largest group is 3.

Example 2:

Input: words = [“a”,”ab”,”abc”]

Output: [1,3]

Explanation:

Since all strings are connected to each other, they should be grouped together.

Thus, the size of the largest group is 3.

Constraints:

Solution

class Solution {
    fun groupStrings(words: Array<String>): IntArray {
        val map = HashMap<Int, Int>()
        for (word in words) {
            var bitmask = 0
            for (ch in word.toCharArray()) {
                bitmask = bitmask or (1 shl ch.code - 'a'.code)
            }
            map[bitmask] = map.getOrDefault(bitmask, 0) + 1
        }
        val keyset: MutableList<Int> = ArrayList()
        for (key in map.keys) {
            keyset.add(key)
        }
        var totalGroups = 0
        var maxSize = 0
        for (key in keyset) {
            if (!map.containsKey(key)) {
                continue
            }
            totalGroups++
            val size = dfs(key, map)
            maxSize = Math.max(size, maxSize)
        }
        return intArrayOf(totalGroups, maxSize)
    }

    private fun dfs(key: Int, map: HashMap<Int, Int>): Int {
        if (!map.containsKey(key)) {
            return 0
        }
        var size = map[key]!!
        map.remove(key)
        for (i in 0..25) {
            size += dfs(key xor (1 shl i), map)
        }
        for (i in 0..25) {
            if (key and (1 shl i) > 0) {
                for (j in 0..25) {
                    if (key and (1 shl j) == 0) {
                        size += dfs(key xor (1 shl i) xor (1 shl j), map)
                    }
                }
            }
        }
        return size
    }
}