查找下一个有效 Table
Finding Next Valid Table
我们得到了一个距离列表,比如距离 = [2, 4, 1]。 tables 的数量是距离的长度 + 1,因此在我们的示例中我们将有 4 tables。对于每个 table 我们需要找到下一个有效的 table 以便 table j 和 i 之间的距离大于或等于 6 英尺。如果不存在这样的 table,则将 j 的下一个有效 table 设置为 0。此外,单个 table 的宽度为 1 英尺。所以在我们的例子中我们有:
t1 -- t2 ---- t3 - t4
where a single dash represents 1ft.
Next valid table for t1 is 0
Next valid table for t2 is 0
Next valid table for t3 is t1 because they share a distance of 7ft between them
Next valid table for t4 is t2 because they share a distance of 6ft between them
如何计算出每个 table 的下一个有效 table?我注意到第一个 table 是特殊的,因为它之前没有其他 table 所以它的下一个有效 table 将自动设置为 0。我还发现有子问题需要被解决(所以我想我可以用自下而上的动态编程方式来做)。下一个 table 的解决方案将取决于其前一个 table 的解决方案。这是我想出的一些逻辑:
if distance between table i and i-1 is >= 6:
next valid table for i is i-1
elif table i-1 has a next valid, table i's next valid will be table (i-1) next valid + 1
else:
# Stuck here on how to find the next valid table
我觉得我在正确的轨道上获得了这个 O(n),但我需要一点额外的帮助。
列出 table 个位置并维护指向正确 table 的指针,这是下一个 i.
的答案
2 4 1
0 3 8 10
t1 t2 t3 t4
t1 0 ptr 0
t2 0 ptr 0
t3 t1 ptr t1
t4 t2 ptr t2
左指针最多增加O(n)
次,我们将使用O(n)
次额外space.
我使用的方法不是动态规划,而是保留一个尾随指针,该指针跟随距离列表的前向迭代,紧靠参数指定的 max_distance
间隙。每当它可以安全地指向一个新的 table 并且仍然满足所需的距离间隙时,这个尾随指针就会增加。对于每条指令,指针告诉我们哪个 table 是“下一个”(实际上,“前一个”相对于前向迭代,“下一个”相对于后向迭代)。
其他一切都是簿记问题,以确保该指针位于正确的位置。这是烦人的部分。
时间复杂度是线性的,因为推动后向指针的内部循环执行的总次数永远不会超过 n
次。 Space 复杂度为 O(1)。
def next_valid_tables(dists, max_dist):
# keeps track of the gap between the left index and the current table
running_dist = 0
# O(n), makes the coding easier but not a necessary expense
dists = [0] + dists
left = 0
result = []
for i, dist in enumerate(dists):
running_dist += dist
# Move the left index forward as long as we can still
# satisfy the running_dist >= max_dist requirement.
# The - 1 and + 1s handle the width of a single table.
while left < i and running_dist - dists[left] - 1 >= max_dist:
running_dist -= dists[left] + 1
left += 1
running_dist += 1 # Add the width of this table
# The left pointer now points at the nearest valid table
# (or 0) so it's the result for this element
result.append(left)
return result
if __name__ == "__main__":
print(next_valid_tables([2, 4, 1], 6)) # => [0, 0, 1, 2]
# 1 2 3 4 <-- table idxes
# 4 4 1 <-- dists
# 0 1 2 2 <-- next table idxes
print(next_valid_tables([4, 4, 1], 2)) # => [0, 1, 2, 2]
# 1 2 3 4 <-- table idxes
# 2 4 1 <-- dists
# 0 1 2 2 <-- next table idxes
print(next_valid_tables([2, 1, 1, 1, 1, 2, 6,], 6)) # => [0, 0, 0, 1, 1, 2, 4, 7]
# 1 2 3 4 5 6 7 8 <-- table idxes
# 2 1 1 1 1 2 6 <-- dists
# 0 0 0 1 1 2 4 7 <-- next table idxes
我们得到了一个距离列表,比如距离 = [2, 4, 1]。 tables 的数量是距离的长度 + 1,因此在我们的示例中我们将有 4 tables。对于每个 table 我们需要找到下一个有效的 table 以便 table j 和 i 之间的距离大于或等于 6 英尺。如果不存在这样的 table,则将 j 的下一个有效 table 设置为 0。此外,单个 table 的宽度为 1 英尺。所以在我们的例子中我们有:
t1 -- t2 ---- t3 - t4
where a single dash represents 1ft.
Next valid table for t1 is 0
Next valid table for t2 is 0
Next valid table for t3 is t1 because they share a distance of 7ft between them
Next valid table for t4 is t2 because they share a distance of 6ft between them
如何计算出每个 table 的下一个有效 table?我注意到第一个 table 是特殊的,因为它之前没有其他 table 所以它的下一个有效 table 将自动设置为 0。我还发现有子问题需要被解决(所以我想我可以用自下而上的动态编程方式来做)。下一个 table 的解决方案将取决于其前一个 table 的解决方案。这是我想出的一些逻辑:
if distance between table i and i-1 is >= 6:
next valid table for i is i-1
elif table i-1 has a next valid, table i's next valid will be table (i-1) next valid + 1
else:
# Stuck here on how to find the next valid table
我觉得我在正确的轨道上获得了这个 O(n),但我需要一点额外的帮助。
列出 table 个位置并维护指向正确 table 的指针,这是下一个 i.
的答案 2 4 1
0 3 8 10
t1 t2 t3 t4
t1 0 ptr 0
t2 0 ptr 0
t3 t1 ptr t1
t4 t2 ptr t2
左指针最多增加O(n)
次,我们将使用O(n)
次额外space.
我使用的方法不是动态规划,而是保留一个尾随指针,该指针跟随距离列表的前向迭代,紧靠参数指定的 max_distance
间隙。每当它可以安全地指向一个新的 table 并且仍然满足所需的距离间隙时,这个尾随指针就会增加。对于每条指令,指针告诉我们哪个 table 是“下一个”(实际上,“前一个”相对于前向迭代,“下一个”相对于后向迭代)。
其他一切都是簿记问题,以确保该指针位于正确的位置。这是烦人的部分。
时间复杂度是线性的,因为推动后向指针的内部循环执行的总次数永远不会超过 n
次。 Space 复杂度为 O(1)。
def next_valid_tables(dists, max_dist):
# keeps track of the gap between the left index and the current table
running_dist = 0
# O(n), makes the coding easier but not a necessary expense
dists = [0] + dists
left = 0
result = []
for i, dist in enumerate(dists):
running_dist += dist
# Move the left index forward as long as we can still
# satisfy the running_dist >= max_dist requirement.
# The - 1 and + 1s handle the width of a single table.
while left < i and running_dist - dists[left] - 1 >= max_dist:
running_dist -= dists[left] + 1
left += 1
running_dist += 1 # Add the width of this table
# The left pointer now points at the nearest valid table
# (or 0) so it's the result for this element
result.append(left)
return result
if __name__ == "__main__":
print(next_valid_tables([2, 4, 1], 6)) # => [0, 0, 1, 2]
# 1 2 3 4 <-- table idxes
# 4 4 1 <-- dists
# 0 1 2 2 <-- next table idxes
print(next_valid_tables([4, 4, 1], 2)) # => [0, 1, 2, 2]
# 1 2 3 4 <-- table idxes
# 2 4 1 <-- dists
# 0 1 2 2 <-- next table idxes
print(next_valid_tables([2, 1, 1, 1, 1, 2, 6,], 6)) # => [0, 0, 0, 1, 1, 2, 4, 7]
# 1 2 3 4 5 6 7 8 <-- table idxes
# 2 1 1 1 1 2 6 <-- dists
# 0 0 0 1 1 2 4 7 <-- next table idxes