【发布时间】:2020-07-29 05:58:20
【问题描述】:
我试图理解一个似乎使用动态编程的编程难题的 Python 解决方案。我能够遵循大多数解决方案,但我正在努力真正正式化解决方案。
问题表述如下:
给你一个整数数组
A。从一些起始索引,您可以 进行一系列跳跃。 (1st, 3rd, 5th, ...) 系列中的跳跃 被称为“奇数”编号的跳跃,并且 (2nd, 4th, 6th, ...) 跳跃 该系列被称为偶数跳跃。您可以通过以下方式从索引
i向前跳转到索引j(使用i < j):
在 奇数 编号的跳转(即跳转 1、3、5,...)期间,您跳转到索引
j这样A[i] <= A[j]和A[j]是可能的最小值。如果有 是多个这样的索引j,你只能跳转到最小的这样 索引 j。在 偶数 编号的跳跃(即,跳跃 2、4、6,...)期间,您会跳跃 到索引
j这样A[i] >= A[j]和A[j]是可能的最大 价值。如果有多个这样的索引j,只能跳转到 最小这样的索引j。对于某些索引
i可能是不合法跳转。一个起始索引是好的,如果从该索引开始,您可以通过跳跃若干次(可能是 0 次或多次)到达数组的末尾。
我们要求您返回良好起始指数的数量。
下面我展示了一些作者发表的解决这个问题的 Python 解决方案。我了解它是如何构建oddnext 和evennext 以及这些数组在技术上持有什么(从该索引以奇数或偶数跳转的索引位置)。我不明白的是最后一个循环是如何工作的,以及它背后的精确动态规划公式是什么。
def odd_even_jumps(self, A):
N = len(A)
def make(B):
ans = [None] * N
stack = [] # invariant: stack is decreasing
for i in B:
while stack and i > stack[-1]:
ans[stack.pop()] = i
stack.append(i)
return ans
B = sorted(range(N), key = lambda i: A[i])
oddnext = make(B)
B.sort(key = lambda i: -A[i])
evennext = make(B)
odd = [False] * N
even = [False] * N
odd[N-1] = even[N-1] = True
# Why does this loop start from the end?
for i in range(N-2, -1, -1):
if oddnext[i] is not None:
odd[i] = even[oddnext[i]]
if evennext[i] is not None:
even[i] = odd[evennext[i]]
return sum(odd)
【问题讨论】:
-
你在跟踪程序时学到了什么?当您使用各种测试阵列打印
odd和even时,您得到了什么?我没有在这个问题中看到这些努力。 -
谢谢@Prune 我刚刚更新了 OP 以澄清这一点,并发布了我自己对这个问题的回答。我试图让它对其他可能想了解这个问题如何接受动态编程解决方案以及如何形式化它的人尽可能有用。
标签: python arrays algorithm dynamic-programming