LeetCode in Kotlin

2719. Count of Integers

Hard

You are given two numeric strings num1 and num2 and two integers max_sum and min_sum. We denote an integer x to be good if:

Return the number of good integers. Since the answer may be large, return it modulo 109 + 7.

Note that digit_sum(x) denotes the sum of the digits of x.

Example 1:

Input: num1 = “1”, num2 = “12”, min_sum = 1, max_sum = 8

Output: 11

Explanation: There are 11 integers whose sum of digits lies between 1 and 8 are 1,2,3,4,5,6,7,8,10,11, and 12. Thus, we return 11.

Example 2:

Input: num1 = “1”, num2 = “5”, min_sum = 1, max_sum = 5

Output: 5

Explanation: The 5 integers whose sum of digits lies between 1 and 5 are 1,2,3,4, and 5. Thus, we return 5.

Constraints:

Solution

class Solution {
    private lateinit var dp: Array<Array<Array<IntArray>>>
    private fun countStrings(i: Int, tight1: Boolean, tight2: Boolean, sum: Int, num1: String, num2: String): Int {
        if (sum < 0) return 0
        if (i == num2.length) return 1
        if (dp[i][if (tight1) 1 else 0][if (tight2) 1 else 0][sum] != -1) {
            return dp[i][if (tight1) 1 else 0][if (tight2) 1 else 0][sum]
        }
        val lo = if (tight1) num1[i].code - '0'.code else 0
        val hi = if (tight2) num2[i].code - '0'.code else 9
        var count = 0
        for (idx in lo..hi) {
            count = (
                count % MOD + countStrings(
                    i + 1,
                    tight1 and (idx == lo), tight2 and (idx == hi),
                    sum - idx, num1, num2,
                ) % MOD
                ) % MOD
        }
        return count.also { dp[i][if (tight1) 1 else 0][if (tight2) 1 else 0][sum] = it }
    }

    fun count(num1: String, num2: String, minSum: Int, maxSum: Int): Int {
        val maxLength = num2.length
        val minLength = num1.length
        val leadingZeroes = maxLength - minLength
        val num1extended: String = "0".repeat(leadingZeroes) + num1
        dp = Array(maxLength) {
            Array(2) {
                Array(2) {
                    IntArray(401)
                }
            }
        }
        for (dim1 in dp) {
            for (dim2 in dim1) {
                for (dim3 in dim2) {
                    dim3.fill(-1)
                }
            }
        }
        val total = countStrings(0, true, true, maxSum, num1extended, num2)
        val unnecessary = countStrings(0, true, true, minSum - 1, num1extended, num2)
        var ans = (total - unnecessary) % MOD
        if (ans < 0) {
            ans += MOD
        }
        return ans
    }

    companion object {
        private const val MOD = 1e9.toInt() + 7
    }
}