创建一个 returns 所有 P 位数字的回溯程序,使得每 3 个连续数字总和为 S
Create a backtracking program that returns all P-digit numbers such that every 3 consecutive digit sums up to S
作为一个问题,我们的任务是编写一个递归回溯程序,打印所有数字为 P
的数字,使得该数字的每 3 个连续数字总和为 S
。
我还不能制定递归回溯方法,但我能够用简单的循环和完整的搜索来创建一个。
def count(P, S):
if P >= 3:
for number in range(10**(P-1), (10**P)):
string = str(number) # I converted it to string to easily access every digit of the number.
isEqual = True
for digit in range(0, len(str(i))-2):
if int(string[digit]) + int(string[digit + 1]) + int(string[digit + 2]) != S:
isEqual = False
break
if isEqual: print(i)
它是如何递归完成的?
这是一个简单且未优化的版本:
max_digits = 5
tot_sum = 12
max_digit = 9
min_digit = 0
digits = {x for x in range(min_digit, max_digit + 1)}
def print_valid_number(cur_digit_i, max_digits, tot_sum, last_2sum, digits, cur_num):
if cur_digit_i == max_digits:
print(''.join(map(str, cur_num)))
return
cur_digits = set(digits)
if cur_digit_i == 0 and 0 in cur_digits:
cur_digits.remove(0)
for d in cur_digits:
if last_2sum + d == tot_sum or cur_digit_i == 0 or cur_digit_i == 1:
cur_num.append(d)
next_last_2sum = d + (0 if cur_digit_i == 0 else cur_num[cur_digit_i - 1])
print_valid_number(cur_digit_i + 1, max_digits, tot_sum, next_last_2sum, digits, cur_num)
cur_num.pop()
print_valid_number(0, max_digits, tot_sum, 0, digits, [])
您基本上在每个递归步骤中传递了最后 2 位数字 (last_2sum
) 的总和,并且对于每个数字,检查是否 last_2sum + current_digit == S
。唯一的例外是前 2 个索引,您只需循环所有 9/10 数字。
代码应该不难理解,但是从简短的描述中可以看出你有很多可以优化的地方。这里有几个:
- 您可以限制可能的数字范围。例如,如果
S == 20
,在最后的数字中你肯定找不到数字 1
。相反,如果 S == 8
,最高位将是 8。
- 可以通过优化前2个索引来减少递归次数(几乎没有什么特别之处)
- 如果你运行这段代码,你会发现从第4位开始,前3位是重复的。这是一个巨大的优化。
作为一个问题,我们的任务是编写一个递归回溯程序,打印所有数字为 P
的数字,使得该数字的每 3 个连续数字总和为 S
。
我还不能制定递归回溯方法,但我能够用简单的循环和完整的搜索来创建一个。
def count(P, S):
if P >= 3:
for number in range(10**(P-1), (10**P)):
string = str(number) # I converted it to string to easily access every digit of the number.
isEqual = True
for digit in range(0, len(str(i))-2):
if int(string[digit]) + int(string[digit + 1]) + int(string[digit + 2]) != S:
isEqual = False
break
if isEqual: print(i)
它是如何递归完成的?
这是一个简单且未优化的版本:
max_digits = 5
tot_sum = 12
max_digit = 9
min_digit = 0
digits = {x for x in range(min_digit, max_digit + 1)}
def print_valid_number(cur_digit_i, max_digits, tot_sum, last_2sum, digits, cur_num):
if cur_digit_i == max_digits:
print(''.join(map(str, cur_num)))
return
cur_digits = set(digits)
if cur_digit_i == 0 and 0 in cur_digits:
cur_digits.remove(0)
for d in cur_digits:
if last_2sum + d == tot_sum or cur_digit_i == 0 or cur_digit_i == 1:
cur_num.append(d)
next_last_2sum = d + (0 if cur_digit_i == 0 else cur_num[cur_digit_i - 1])
print_valid_number(cur_digit_i + 1, max_digits, tot_sum, next_last_2sum, digits, cur_num)
cur_num.pop()
print_valid_number(0, max_digits, tot_sum, 0, digits, [])
您基本上在每个递归步骤中传递了最后 2 位数字 (last_2sum
) 的总和,并且对于每个数字,检查是否 last_2sum + current_digit == S
。唯一的例外是前 2 个索引,您只需循环所有 9/10 数字。
代码应该不难理解,但是从简短的描述中可以看出你有很多可以优化的地方。这里有几个:
- 您可以限制可能的数字范围。例如,如果
S == 20
,在最后的数字中你肯定找不到数字1
。相反,如果S == 8
,最高位将是 8。 - 可以通过优化前2个索引来减少递归次数(几乎没有什么特别之处)
- 如果你运行这段代码,你会发现从第4位开始,前3位是重复的。这是一个巨大的优化。