- Translate each rule into one explicit state update.
- Maintain the invariant after every processed item.
- Return the accumulated state once all relevant input has been handled.
Code notes
- 109 lines of Python from the credited upstream file count-numbers-with-non-decreasing-digits.py.
- The implementation visibly relies on sequence storage, ordered lookup.
- No explicit loop blocks detected.
Complexity
Count the number and nesting of passes over the input, then include the maintained containers in the memory estimate.
Check the problem constraints before deciding whether this complexity will pass.
Use this to learn the idea, then write your own version.
123 45class Solution(object):6 def countNumbers(self, l, r, b):7 """8 :type l: str9 :type r: str10 :type b: int11 :rtype: int12 """13 MOD = 10**9+714 fact, inv, inv_fact = [[1]*2 for _ in xrange(3)]15 def nCr(n, k):16 while len(inv) <= n: 17 fact.append(fact[-1]*len(inv) % MOD)18 inv.append(inv[MOD%len(inv)]*(MOD-MODlen(inv)) % MOD) 19 inv_fact.append(inv_fact[-1]*inv[-1] % MOD)20 return (fact[n]*inv_fact[n-k] % MOD) * inv_fact[k] % MOD21 22 def nHr(n, k):23 return nCr(n+k-1, k)24 25 def count(x):26 digits_base = []27 while x:28 x, r = divmod(x, b)29 digits_base.append(r)30 digits_base.reverse()31 if not digits_base:32 digits_base.append(0)33 result = 034 for i in xrange(len(digits_base)):35 if i-1 >= 0 and digits_base[i-1] > digits_base[i]:36 break37 for j in xrange(digits_base[i-1] if i-1 >= 0 else 0, digits_base[i]):38 result = (result + nHr((b-1)-j+1, len(digits_base)-(i+1))) % MOD39 else:40 result = (result+1)%MOD41 return result42 43 return (count(int(r)) - count(int(l)-1)) % MOD44 45 46474849class Solution2(object):50 def countNumbers(self, l, r, b):51 """52 :type l: str53 :type r: str54 :type b: int55 :rtype: int56 """57 MOD = 10**9+758 fact, inv, inv_fact = [[1]*2 for _ in xrange(3)]59 def nCr(n, k):60 while len(inv) <= n: 61 fact.append(fact[-1]*len(inv) % MOD)62 inv.append(inv[MOD%len(inv)]*(MOD-MODlen(inv)) % MOD) 63 inv_fact.append(inv_fact[-1]*inv[-1] % MOD)64 return (fact[n]*inv_fact[n-k] % MOD) * inv_fact[k] % MOD65 66 def nHr(n, k):67 return nCr(n+k-1, k)68 69 def decrease(digits):70 for i in reversed(xrange(len(digits))):71 if digits[i]:72 digits[i] -= 173 break74 digits[i] = 975 76 def divide(digits, base):77 result = []78 r = 079 for d in digits:80 q, r = divmod(r*10+d, base)81 if result or q:82 result.append(q)83 return result, r84 85 def to_base(digits, base):86 result = []87 while digits:88 digits, r = divide(digits, base)89 result.append(r)90 result.reverse()91 return result92 93 def count(digits):94 digits_base = to_base(digits, b)95 result = 096 for i in xrange(len(digits_base)):97 if i-1 >= 0 and digits_base[i-1] > digits_base[i]:98 break99 for j in xrange(digits_base[i-1] if i-1 >= 0 else 0, digits_base[i]):100 result = (result + nHr((b-1)-j+1, len(digits_base)-(i+1))) % MOD101 else:102 result = (result+1)%MOD103 return result104 105 digits_l = map(int, l)106 decrease(digits_l)107 digits_r = map(int, r)108 return (count(digits_r) - count(digits_l)) % MOD109