Skip to content

Latest commit

 

History

History

1416. Restore The Array

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 

Tag: Dynamic Programming

Difficulty: Hard

A program was supposed to print an array of integers. The program forgot to print whitespaces and the array is printed as a string of digits s and all we know is that all integers in the array were in the range [1, k] and there are no leading zeros in the array.

Given the string s and the integer k, return the number of the possible arrays that can be printed as s using the mentioned program. Since the answer may be very large, return it modulo 109+ 7.


Example 1:

Input: s = "1000", k = 10000
Output: 1
Explanation: The only possible array is [1000]

Example 2:

Input: s = "1000", k = 10
Output: 0
Explanation: There cannot be an array that was printed this way and has all integer >= 1 and <= 10.

Example 3:

Input: s = "1317", k = 2000
Output: 8
Explanation: Possible arrays are [1317],[131,7],[13,17],[1,317],[13,1,7],[1,31,7],[1,3,17],[1,3,1,7]

Constraints:

  • 1 <= s.length <= 105
  • s consists of only digits and does not contain leading zeros.
  • 1 <= k <= 109

The Framework

Top-Down Dynamic Programming

Algorithm

  1. Create an array memo of size m + 1, to store the value of dp(x).

  2. To get the value of dp(start), if a non-zero dp[start] exists, it means we have already got its value, return dp[start]. Otherwise:

  • If s[start] == 0, return 0.
  • If start = m, return 1.
  • Initialize count = 0, the number of valid arrays.
  • Then we look for every possible ending index end by iterating over indexes from start. If s[start ~ end] represents a valid integer, we continue looking for the subproblem dp(end + 1) and update count as count += dp(end + 1).
  • Update memo[start] as dp(start).
  1. Return dp(0).
class Solution:
    def numberOfArrays(self, s: str, k: int) -> int:
        memo = collections.defaultdict(int)
        m, n = len(s), len(str(k))
        mod = 10**9 + 7

        def dp(start):
            # Base cases
            # If reached the last character of s, return 1
            if start == m:
                return 1
            
            # Avoid leading zero's
            if s[start] == '0':
                return 0
            
            if start in memo:
                return memo[start]

            # Recurrence relation: for all possible starting number, add the number of arrays that can be printed as the remaining string to count.
            count = 0
            for end in range(start, m):
                curr = s[start:end + 1]
                if int(curr) > k:
                    break
                count += dp(end + 1)
            
            memo[start] = count % mod
            return count

        return dp(0) % mod
class Solution:
    def numberOfArrays(self, s: str, k: int) -> int:
        m, n = len(s), len(str(k))
        mod = 10**9 + 7

        @lru_cache(None)
        def dp(start):
            # Base cases
            # If reached the last character of s, return 1
            if start == m:
                return 1
            
            # Avoid leading zero's
            if s[start] == '0':
                return 0

            # Recurrence relation
            count = 0
            for end in range(start, m):
                curr = s[start:end + 1]
                if int(curr) > k:
                    break
                count += dp(end + 1)

            return count % mod

        return dp(0) % mod

Bottom-Up Dynamic Programming