LeetCode in Kotlin

297. Serialize and Deserialize Binary Tree

Hard

Serialization is the process of converting a data structure or object into a sequence of bits so that it can be stored in a file or memory buffer, or transmitted across a network connection link to be reconstructed later in the same or another computer environment.

Design an algorithm to serialize and deserialize a binary tree. There is no restriction on how your serialization/deserialization algorithm should work. You just need to ensure that a binary tree can be serialized to a string and this string can be deserialized to the original tree structure.

Clarification: The input/output format is the same as how LeetCode serializes a binary tree. You do not necessarily need to follow this format, so please be creative and come up with different approaches yourself.

Example 1:

Input: root = [1,2,3,null,null,4,5]

Output: [1,2,3,null,null,4,5]

Example 2:

Input: root = []

Output: []

Constraints:

Solution

import com_github_leetcode.TreeNode

/*
 * Definition for a binary tree node.
 * class TreeNode(var `val`: Int) {
 *     var left: TreeNode? = null
 *     var right: TreeNode? = null
 * }
 */

class Codec {
    private var offset = 0

    // Encodes a tree to a single string.
    fun serialize(root: TreeNode?): String {
        val sb = StringBuilder()
        offset = 0
        serialize(root, sb)
        return sb.toString()
    }

    fun serialize(root: TreeNode?, sb: StringBuilder) {
        // all nodes fit into 4 bits.
        // IFF we offset at 0. So encode(val) = val + min(default - 1000)
        if (root == null) {
            sb.append(DELIM)
            return
        }
        val s = Integer.toHexString(root.`val` + BASE_OFFSET)
        val sb2 = StringBuilder()
        for (i in 0 until 3 - s.length) {
            sb2.append('0')
        }
        sb2.append(s)
        sb.append(sb2)
        serialize(root.left, sb)
        serialize(root.right, sb)
    }

    // Decodes your encoded data to tree.
    fun deserialize(data: String): TreeNode? {
        if (data[offset] == '*') {
            offset++
            return null
        }
        val root = TreeNode(
            data.substring(offset, offset + 3).toInt(16) - BASE_OFFSET,
        )
        offset += 3
        root.left = deserialize(data)
        root.right = deserialize(data)
        return root
    }

    companion object {
        private const val BASE_OFFSET = 1000
        private const val DELIM = "*"
    }
}

/*
 * Your Codec object will be instantiated and called as such:
 * var ser = Codec()
 * var deser = Codec()
 * var data = ser.serialize(longUrl)
 * var ans = deser.deserialize(data)
 */