Tag
: Dynamic Programming
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
Algorithm
-
Create an array
memo
of sizem + 1
, to store the value ofdp(x)
. -
To get the value of
dp(start)
, if a non-zerodp[start]
exists, it means we have already got its value, returndp[start]
. Otherwise:
- If
s[start] == 0
, return0
. - If
start = m
, return1
. - Initialize
count = 0
, the number of valid arrays. - Then we look for every possible ending index
end
by iterating over indexes fromstart
. Ifs[start ~ end]
represents a valid integer, we continue looking for the subproblemdp(end + 1)
and update count ascount += dp(end + 1)
. - Update
memo[start]
asdp(start)
.
- 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