我正在尝试在Python3中解决这个问题。我知道如何找到min1和min2,但我不知道如何在一次传递中搜索5个元素。
输入程序以 1 分钟的间隔提供设备执行的测量。所有数据的自然数均不超过 1000 。 问题是要找到间隔不小于5分钟的两次测量的最小平方和。第一行将包含一个自然数 - 测量次数 N < / em>的。保证 5&lt; N <= 10000 。以下 N 行中的每一行都包含一个自然数 - 下一次测量的结果。
你的程序应该输出一个数字,这是两次测量的平方的最小和,间隔不小于5分钟。
示例输入: 9 12 45 的 5 4 21 20 10 的 12 26
预期产出:169
答案 0 :(得分:0)
我喜欢这个问题。有趣的脑筋急转弯。 :)
我注意到你的样本输入是range(1, 100)
中的所有整数并且有一些重复,所以我生成了如下样本列表:
>>> import random
>>> sample_list = [random.choice(range(1, 100)) for i in range(10)]
>>> sample_list
[74, 68, 57, 18, 36, 8, 89, 73, 77, 80]
根据问题陈述,这些数字代表以一分钟为间隔测量的数据,我们的一个限制是我们的结果必须代表至少相隔五分钟收集的数据。最终,这意味着原始列表中的数据索引必须相差至少五个。换句话说,对于任何两个输入v1
和v2
:
abs(sample_list.index(v1) - sample_list.index(v2)) >= 5
必须是真的。我们也知道我们正在寻找最小的总和,所以先查看最小的数字会有所帮助。
因此,我首先将sample_list中的值映射到它们出现的索引,然后对它们进行排序:
>>> occurrences = {}
>>> for index, value in enumerate(sample_list):
... try:
... occurrences[value].append(index)
... except KeyError:
... occurrences[value] = [index]
...
>>> occurrences
{80: [9], 18: [3], 68: [1], 73: [7], 89: [6], 8: [5], 57: [2], 74: [0], 77: [8], 36: [4]}
>>> sorted_occurrences = sorted(occurrences)
>>> sorted_occurrences
[8, 18, 36, 57, 68, 73, 74, 77, 80, 89]
经过大量的反复试验,这就是我最终在函数形式中提出的内容(包括之前讨论过的一些内容):
def smallest_sum_of_squares_five_apart(sample):
occurrences = {}
for index, value in enumerate(sample):
try:
occurrences[value].append(index)
except KeyError:
occurrences[value] = [index]
sorted_occurrences = sorted(occurrences)
least_sum = 0
for index, v1 in enumerate(sorted_occurrences):
if least_sum and v1**2 > least_sum:
return least_sum
for v2 in sorted_occurrences[:index+1]:
if (abs(max(occurrences[v1]) - min(occurrences[v2])) >= 5 or
abs(max(occurrences[v2]) - min(occurrences[v1])) >= 5):
print('Found candidates:', str((v1, v2)))
sum_of_squares = v1**2 + v2**2
if not least_sum or sum_of_squares < least_sum:
least_sum = sum_of_squares
return least_sum
这里的想法是:
不幸的是,找到第一个是不够的。根据列表的构造方式,它不会总是以这种方式找到最小的对。实际上,它不适用于您自己的样本输入。但是,一旦v1**2
(较大值的平方)大于总和,我们知道,因为所有数字都是自然数,所以继续查看是没有意义的。
我在下面列出了完整的可运行实现。它需要一个命令行参数(默认值为10),表示随机生成的样本中所需的项目数。它将打印随机生成的样本以及它检查的所有候选对,最后是总和本身。我已经多次在10个大小的输入上检查了这个,它似乎一般都在工作。但是,如果不正确,欢迎提供反馈。另请注意,您可以从问题中取消注释示例列表,看看它是如何工作的(并且它得到了正确答案)。
import random
import sys
def smallest_sum_of_squares_five_apart(sample):
occurrences = {}
for index, value in enumerate(sample):
try:
occurrences[value].append(index)
except KeyError:
occurrences[value] = [index]
sorted_occurrences = sorted(occurrences)
least_sum = 0
for index, v1 in enumerate(sorted_occurrences):
if least_sum and v1**2 > least_sum:
return least_sum
for v2 in sorted_occurrences[:index+1]:
if (abs(max(occurrences[v1]) - min(occurrences[v2])) >= 5 or
abs(max(occurrences[v2]) - min(occurrences[v1])) >= 5):
print('Found candidates:', str((v1, v2)))
sum_of_squares = v1**2 + v2**2
if not least_sum or sum_of_squares < least_sum:
least_sum = sum_of_squares
return least_sum
if __name__ == '__main__':
try:
r = int(sys.argv[1])
except IndexError:
r = 10
sample_list = [random.choice(range(1, 100)) for i in range(r)]
#sample_list = [9, 12, 45, 5, 4, 21, 20, 10, 12, 26]
print(sample_list)
print(smallest_sum_of_squares_five_apart(sample_list))
答案 1 :(得分:0)
试试这个:
#!/usr/bin/env python3
import queue
inp = [9,12,45,5,4,21,20,10,12,26]
q = queue.Queue() #Make a new queue
smallest = False #No smallest number, yet
best = False #No best sum of squares, yet
for x in inp:
q.put(x) #Place current element on queue
#If there's an item from more than five minutes ago, consider it
if q.qsize()>5:
temp = q.get() #Pop oldest item from queue into temporary variable
if not smallest: #If this is the first item more than 5 minutes old
smallest = temp #it is the smallest item by default
else: #otherwise...
smallest = min(temp,smallest) #only store it if it is the smallest yet
#If we have no best sum of squares or the current item produces one, then
#save it as the best
if (not best) or (x*x+smallest*smallest<best):
best = x*x+smallest*smallest
print(best)
我的想法是走遍队列,跟踪我们已经看到的最小元素,这个元素超过五分钟,并将它与最新元素进行比较,跟踪我们前进的最小平方和。
我认为如果你仔细想想,你会发现答案非常直观。
该算法在O(N)时间内运行。