Python 解释'的逻辑;相邻数字绝对差值不超过K'的N位数字计数;详细地

Python 解释'的逻辑;相邻数字绝对差值不超过K'的N位数字计数;详细地,python,python-3.x,algorithm,multidimensional-array,dynamic-programming,Python,Python 3.x,Algorithm,Multidimensional Array,Dynamic Programming,有人能帮我理解一下在Geeksforgeks.com上发现的动态编程问题的逻辑吗。我无法理解,即使经过提供的答案 问题: 具有相邻数字绝对差的N位数字计数 不超过K |集2 给定两个整数N和K,任务是 求N位数的计数,使 数字中的相邻数字不大于K 示例: 输入:N=2,K=1 产出:26 说明:数字是10,11, 12, 21, 22, 23, 32, 33, 34, 43, 44, 45, 54, 55, 56, 65, 66, 67, 76, 77,78,87,88,89,98,99 输入:

有人能帮我理解一下在Geeksforgeks.com上发现的动态编程问题的逻辑吗。我无法理解,即使经过提供的答案

问题:

具有相邻数字绝对差的N位数字计数 不超过K |集2

给定两个整数N和K,任务是 求N位数的计数,使 数字中的相邻数字不大于K

示例:

输入:N=2,K=1

产出:26

说明:数字是10,11, 12, 21, 22, 23, 32, 33, 34, 43, 44, 45, 54, 55, 56, 65, 66, 67, 76, 77,78,87,88,89,98,99

输入:N=3,K=2

产出:188

Python3溶液:

# Function to return the count of such numbers 
def getCount(n, K): 
    # For 1-digit numbers, the count is 10 irrespective of K 
    if(n == 1): 
        return 10

    # dp[j] stores the number of such i-digit numbers ending with j 
    dp = [0] * 11

    # Stores the results of length i 
    next = [0] * 11

    # Initialize count for 1-digit numbers 
    for i in range(1, 9 + 1): 
        dp[i] = 1

    # Compute values for count of digits greater than 1 
    for i in range(2, n + 1): 
        for j in range(9 + 1): 
            # Find the range of allowed numbers if last digit is j 
            l = max(0, j - k) 
            r = min(9, j + k) 

            # Perform Range update 
            next[l] += dp[j] 
            next[r + 1] -= dp[j] 

        # Prefix sum to find actual count of i-digit numbers ending with j 
        for j in range(1, 9 + 1): 
            next[j] += next[j - 1] 

        # Update dp[] 
        for j in range(10): 
            dp[j] = next[j] 
            next[j] = 0

    # Stores the final answer 
    count = 0
    for i in range(9 + 1): 
        count += dp[i] 

    return count 


if __name__ == '__main__': 
    n = 2
    k = 1
    print(getCount(n, k)) 
此代码由Shivam Singh提供

链接:

我无法理解下面几行的逻辑

# Compute values for count of 

# digits greater than 1 

for i in range(2, n + 1): 

    for j in range(9 + 1): 



        # Find the range of allowed 

        # numbers if last digit is j 

        l = max(0, j - k) 

        r = min(9, j + k) 



        # Perform Range update 

        next[l] += dp[j] 

        next[r + 1] -= dp[j] 



    # Prefix sum to find actual count 

    # of i-digit numbers ending with j 

    for j in range(1, 9 + 1): 

        next[j] += next[j - 1] 



    # Update dp[] 

    for j in range(10): 

        dp[j] = next[j] 

        next[j] = 0

N=2
所以我们严格处理的是两位数

K=1
因此当前数字中的每个数字不得大于或小于其相邻数字的1位

虽然答案是
26
(这些数字的计数),但让我们看看为什么答案包括
10
11
12
,而不是
13

10
是好的,因为
1
-
0
10
的数字)的绝对值小于或等于
1
K
的值)

13
不好,因为
1
-
3
的绝对值是
2
2
大于
K

请注意,随着
N
的增加,所需的成对数字比较的数量也将增加

我将跳过使用无意义变量名解析其他人的代码。以下是我可能尝试解决此问题的方法:

def is_valid_number(number_to_test, allowed_digit_spread):
    if number_to_test < 10:
        # apparently all 1 digit numbers pass
        return True

    # get the individual digits as a list
    digits = [int(digit) for digit in str(number_to_test)]

    for i in range(1, len(digits)):
        current_digit = digits[i]
        prior_digit = digits[i-1]
        if abs(current_digit - prior_digit) > allowed_digit_spread:
            # bad pairwise compare so reject
            return False

    return True

def get_numbers_to_test(allowed_digits):
    start = pow(10, allowed_digits -1)
    end = pow(10, allowed_digits)
    return range(start, end)

def getCount(allowed_digits, allowed_digit_spread):
    count = 0
    for n in get_numbers_to_test(allowed_digits):
        if is_valid_number(n, allowed_digit_spread):
            count += 1
    return count

if __name__ == '__main__':
    n = 2
    k = 1
    print(getCount(n, k))
def是有效的数字(数字到测试,允许的数字排列):
如果数字_至_测试<10:
#显然所有的1位数字都通过了
返回真值
#以列表形式获取各个数字
数字=[str(数字到测试)中数字的整数(数字)]
对于范围内的i(1,len(位数)):
当前数字=数字[i]
前一位=位[i-1]
如果abs(当前数字-前一数字)>允许的数字排列:
#不好的成对比较,所以拒绝
返回错误
返回真值
def get_编号到_测试(允许的数字):
开始=功率(10,允许的\u位数-1)
end=功率(10,允许的数字)
返回范围(开始、结束)
def getCount(允许的数字、允许的数字排列):
计数=0
对于get_数字到_测试中的n(允许的数字):
如果是有效的数字(n,允许的数字排列):
计数+=1
返回计数
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
n=2
k=1
打印(getCount(n,k))

您不清楚的是什么?提供实际逻辑的部分,对于范围(2,n+1)中的i:对于范围(9+1)中的j:#如果最后一个数字是jl=max(0,j-k)r=min(9,j+k),则查找允许的数字范围#执行范围更新next[l]+=dp[j]next[r+1]-=dp[j]#前缀和以查找范围(1,9+1)内j的以j结尾的i位数字的实际计数:next[j]+=next[j-1]#更新范围(10)内j的dp[]:dp[j]=next[j]=0,我真的不知道这些代码通过偶然的检查能做些什么,我不会接受它作为任务的解决方案或作为代码审查的一部分。这不是一个复杂的问题,解决方案似乎使它成为一个复杂的问题。我的回答是,我试图让问题陈述和潜在解决方案更加清晰,但我想我不会直接回答你的实际问题。谢谢你的回答,但我不清楚的是以下代码中的逻辑:对于范围(2,n+1)中的I:对于范围(9+1)中的j:l=max(0,j-k)r=min(9,j+k)next[l]+=dp[j]next[r+1]-=dp[j]对于范围(1,9+1)内的j:next[j]+=next[j-1]对于范围(10)内的j:dp[j]=next[j]next[j]=0,我真的不知道这些代码通过偶然的检查能做些什么,我不会接受它作为任务的解决方案或作为代码审查的一部分。这不是一个复杂的问题,解决方案似乎使它成为一个。是的,我完全同意。这是一个如此复杂的解决方案。谢谢你的简单回答