题解采用动态规划的思想,结合记忆化搜索的方法来统计步进数字。首先,定义一个多维数组result,其中result[i][j]表示长度为j且以数字i开始的步进数字数量。通过一个预处理步骤,使用动态规划填充这个数组。动态转移方程基于前一位的数字和其相邻数字构建,确保每次构建的数字符合步进数字的要求。在主函数中,使用两个辅助函数来计算范围[low, high]内的步进数字,分别计算小于或等于high的步进数字和小于low的步进数字,然后求差值并校验low是否为步进数字,以得到最终答案。
时间复杂度: O(n)
空间复杂度: O(1)
MOD = 1_000_000_007
adjoin = [[1], [0, 2], [1, 3], [2, 4], [3, 5], [4, 6], [5, 7], [6, 8], [7, 9], [8]]
MAXLENGTH = 102
result = [[0] * MAXLENGTH for _ in range(10)]
resultMix = [[0] * MAXLENGTH for _ in range(10)]
resultLowerSum = [[0] * MAXLENGTH for _ in range(10)]
temp, tempSum = list(range(10)), 10
for i in range(10):
result[i][1] = 1
resultMix[i][1] = 1
resultLowerSum[i][1] = i
for j in range(2, MAXLENGTH):
for i in range(10):
res = 0
for k in adjoin[i]:
res += result[k][j - 1]
result[i][j] = res % MOD
if i > 0:
resultMix[i][j] = (resultMix[i][j - 1] + result[i][j]) % MOD
resultLowerSum[i][j] = tempSum
tempSum = (tempSum + result[i][j]) % MOD
class Solution:
def countSteppingNumbers(self, low: str, high: str) -> int:
def count(li: List[int]) -> int:
length = len(li)
res = resultLowerSum[li[0]][length]
if length == 1:
return res + 1
pre = li[0]
for idx, curNum in enumerate(li[1:], 1):
if curNum < adjoin[pre][0]:
break
if curNum == adjoin[pre][0]:
if idx == length - 1:
res += 1
pre = adjoin[pre][0]
continue
res += result[adjoin[pre][0]][length - idx]
if len(adjoin[pre]) == 1:
break
if adjoin[pre][-1] > curNum:
break
if curNum == adjoin[pre][-1]:
if idx == length - 1:
res += 1
pre = adjoin[pre][-1]
continue
res += result[adjoin[pre][-1]][length - idx]
break
return res
def check(li: List[int]) -> int:
for idx, curNum in enumerate(li[1:], 1):
if abs(curNum - li[idx - 1]) == 1:
continue
else:
return 0
return 1
highList = [int(i) for i in high]
highResult = count(highList)
lowList = [int(i) for i in low]
lowResult = count(lowList)
return (highResult - lowResult + check(lowList)) % MOD