LeetCode in Kotlin

2791. Count Paths That Can Form a Palindrome in a Tree

Hard

You are given a tree (i.e. a connected, undirected graph that has no cycles) rooted at node 0 consisting of n nodes numbered from 0 to n - 1. The tree is represented by a 0-indexed array parent of size n, where parent[i] is the parent of node i. Since node 0 is the root, parent[0] == -1.

You are also given a string s of length n, where s[i] is the character assigned to the edge between i and parent[i]. s[0] can be ignored.

Return the number of pairs of nodes (u, v) such that u < v and the characters assigned to edges on the path from u to v can be rearranged to form a palindrome.

A string is a palindrome when it reads the same backwards as forwards.

Example 1:

Input: parent = [-1,0,0,1,1,2], s = “acaabc”

Output: 8

Explanation:

The valid pairs are:

Example 2:

Input: parent = [-1,0,0,0,0], s = “aaaaa”

Output: 10

Explanation: Any pair of nodes (u,v) where u < v is valid.

Constraints:

Solution

class Solution {
    private fun getMap(parent: List<Int>, s: String, dp: IntArray, idx: Int): Int {
        if (dp[idx] < 0) {
            dp[idx] = 0
            dp[idx] = getMap(parent, s, dp, parent[idx]) xor (1 shl s[idx].code - 'a'.code)
        }
        return dp[idx]
    }

    fun countPalindromePaths(parent: List<Int>, s: String): Long {
        val n: Int = parent.size
        val dp = IntArray(n)
        var ans: Long = 0
        val mapCount: MutableMap<Int, Int> = HashMap()
        dp.fill(-1)
        dp[0] = 0
        for (i in 0 until n) {
            val currMap = getMap(parent, s, dp, i)
            // if map are same, two points can form a path;
            val evenCount = mapCount[currMap] ?: 0
            mapCount.put(currMap, evenCount + 1)
        }
        for (key in mapCount.keys) {
            val value = mapCount[key]!!
            ans += value.toLong() * (value - 1) shr 1
            for (i in 0..25) {
                val base = 1 shl i
                // if this map at i is 1, which means odd this bit
                if (key and base > 0 && mapCount.containsKey(key xor base)) {
                    // key ^ base is the map that is 0 at bit i, odd pairs with even,
                    // can pair and no duplicate
                    ans += value.toLong() * mapCount[key xor base]!!
                }
            }
        }
        return ans
    }
}