LeetCode 2801 (Hard, Acceptance Level 14.5%). Count Stepping Numbers in Range. DP. Efficiently handles large inputs (10^9 + 7).

sergeyleschev

Sergey Leschev

Posted on July 30, 2023

LeetCode 2801 (Hard, Acceptance Level 14.5%). Count Stepping Numbers in Range. DP. Efficiently handles large inputs (10^9 + 7).

Description

Given two positive integers low and high represented as strings, find the count of stepping numbers in the inclusive range [low, high].

A stepping number is an integer such that all of its adjacent digits have an absolute difference of exactly 1.

Return an integer denoting the count of stepping numbers in the inclusive range [low, high].

Since the answer may be very large, return it modulo 10^9 + 7.

Note: A stepping number should not have a leading zero.

Example 1:



Input: low = "1", high = "11"
Output: 10
Explanation: The stepping numbers in the range [1,11] are 1, 2, 3, 4, 5, 6, 7, 8, 9 and 10. There are a total of 10 stepping numbers in the range. Hence, the output is 10.


Enter fullscreen mode Exit fullscreen mode

Example 2:



Input: low = "90", high = "101"
Output: 2
Explanation: The stepping numbers in the range [90,101] are 98 and 101. There are a total of 2 stepping numbers in the range. Hence, the output is 2. 


Enter fullscreen mode Exit fullscreen mode

Constraints:
1 <= int(low) <= int(high) < 10^100
1 <= low.length, high.length <= 100
low and high consist of only digits.
low and high don't have any leading zeros.

LeetCode TOP 200 Sergey Leschev

Intuition

The problem requires finding the count of stepping numbers in a given range [low, high], where a stepping number is an integer such that all its adjacent digits have an absolute difference of exactly 1. To efficiently count these stepping numbers, we can use a dynamic programming approach.

Approach

The Swift solution uses dynamic programming to solve the problem. The rec function recursively calculates the count of stepping numbers based on certain conditions. The dp array is used to store previously computed results, which helps avoid redundant calculations and improves efficiency.

The check function checks if a number is a stepping number by comparing the absolute difference between each pair of adjacent digits.

In the countSteppingNumbers function, we call rec twice for the input range [low, high] and then subtract the count for low from the count for high. Additionally, if low itself is a stepping number, we add 1 to the result.

LeetCode TOP 200 Sergey Leschev

Code (Swift)

The solution efficiently handles large inputs and returns the count of stepping numbers modulo 10^9 + 7, as required by the problem statement.




class Solution {

    let mod = 1_000_000_007

    var dp: [[[[Int]]]] = Array(
        repeating: Array(
            repeating: Array(repeating: Array(repeating: -1, count: 2), count: 10), count: 2),
        count: 101)

    func rec(_ s1: [Character], _ ind: Int, _ smaller: Bool, _ last: Int, _ start: Bool) -> Int {
        if ind == s1.count {
            return 1
        }

        if dp[ind][smaller ? 1 : 0][last][start ? 1 : 0] != -1 {
            return dp[ind][smaller ? 1 : 0][last][start ? 1 : 0]
        }

        var ans = 0

        if start || abs(last - 0) == 1 {
            ans = (ans + rec(s1, ind + 1, smaller || (s1[ind] != "0"), 0, start)) % mod
        }

        if smaller {
            for i in 1...9 {
                if abs(last - i) == 1 || start {
                    ans = (ans + rec(s1, ind + 1, smaller, i, false)) % mod
                }
            }
        } else {
            let diff = Int(String(s1[ind]))!
            if diff > 0 {
                for i in 1..<diff {
                    if abs(last - i) == 1 || start {
                        ans = (ans + rec(s1, ind + 1, true, i, false)) % mod
                    }
                }
            }
            if s1[ind] != "0" {
                if abs(last - diff) == 1 || start {
                    ans = (ans + rec(s1, ind + 1, false, diff, false)) % mod
                }
            }
        }
        dp[ind][smaller ? 1 : 0][last][start ? 1 : 0] = ans
        return ans
    }

    func check(_ s: String) -> Bool {
        let sChars = Array(s)
        for i in 0..<(sChars.count - 1) {
            if abs(Int(String(sChars[i]))! - Int(String(sChars[i + 1]))!) != 1 {
                return false
            }
        }
        return true
    }

    func countSteppingNumbers(_ low: String, _ high: String) -> Int {
        let x = rec(Array(high), 0, false, 0, true)
        dp = Array(
            repeating: Array(
                repeating: Array(repeating: Array(repeating: -1, count: 2), count: 10), count: 2),
            count: 101)
        let y = rec(Array(low), 0, false, 0, true)

        let z = check(low)

        return (x - y + (z ? 1 : 0) + mod) % mod
    }
}




Enter fullscreen mode Exit fullscreen mode

Sources: Github

LeetCode TOP 200 Sergey Leschev


Contacts
I have a clear focus on time-to-market and don't prioritize technical debt. And I took part in the Pre-Sale/RFX activity as a System Architect, assessment efforts for Mobile (iOS-Swift, Android-Kotlin), Frontend (React-TypeScript) and Backend (NodeJS-.NET-PHP-Kafka-SQL-NoSQL). And I also formed the work of Pre-Sale as a CTO from Opportunity to Proposal via knowledge transfer to Successful Delivery.

šŸ›©ļø #startups #management #cto #swift #typescript #database
šŸ“§ Email: sergey.leschev@gmail.com
šŸ‘‹ LinkedIn: https://linkedin.com/in/sergeyleschev/
šŸ‘‹ LeetCode: https://leetcode.com/sergeyleschev/
šŸ‘‹ Twitter: https://twitter.com/sergeyleschev
šŸ‘‹ Github: https://github.com/sergeyleschev
šŸŒŽ Website: https://sergeyleschev.github.io
šŸŒŽ Reddit: https://reddit.com/user/sergeyleschev
šŸŒŽ Quora: https://quora.com/sergey-leschev
šŸŒŽ Medium: https://medium.com/@sergeyleschev
šŸ–Øļø PDF Design Patterns: Download

šŸ’– šŸ’Ŗ šŸ™… šŸš©
sergeyleschev
Sergey Leschev

Posted on July 30, 2023

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related