我正在编写一个小程序,在python中,它将从算术级数中找到一个单独的缺失元素(其中起始元素可以是正数和负数,系列可以是升序或降序)。
所以例如:如果输入是1 3 5 9 11,那么函数应该返回7,因为这是上面AP系列中唯一缺失的元素。 输入格式:输入元素由1个空格分隔,而不是通常所做的逗号。
以下是代码:
def find_missing_elm_ap_series(n, series):
ap = series
ap = ap.split(' ')
ap = [int(i) for i in ap]
cd = []
for i in range(n-1):
cd.append(ap[i+1]-ap[i])
common_diff = 0
if len(set(cd)) == 1:
print 'The series is complete'
return series
else:
cd = [abs(i) for i in cd]
common_diff = min(cd)
if ap[0] > ap[1]:
common_diff = (-1)*common_diff
new_ap = []
for i in range(n+1):
new_ap.append(ap[0] + i*common_diff)
missing_element = set(new_ap).difference(set(ap))
return missing_element
其中n是所提供系列的长度(缺少元素的系列:上例中为5)。
我确信在python中还有其他更简洁,更优雅的编写代码的方法。有人可以帮忙吗? 谢谢 顺便说一句:我自己学习python,因此也是问题。
答案 0 :(得分:3)
基于以下事实:如果缺少一个元素,那么它就是expected-sum(series) - actual-sum(series)
。从n
开始到a
开始的b
元素系列的预期总和为(a+b)*n/2
。剩下的就是Python:
def find_missing(series):
A = map(int, series.split(' '))
a, b, n, sumA = A[0], A[-1], len(A), sum(A)
if (a+b)*n/2 == sumA:
return None #no element missing
return (a+b)*(n+1)/2-sumA
print find_missing("1 3 5 9") #7
print find_missing("-1 1 3 5 9") #7
print find_missing("9 6 0") #3
print find_missing("1 2 3") #None
print find_missing("-3 1 3 5") #-1
答案 1 :(得分:2)
嗯......你可以做得更简单,但它会彻底改变你的算法。
首先,你可以证明算术级数的步骤是ap[1] - ap[0]
,除非ap[2] - ap[1]
的幅度低于它,在这种情况下,缺失的元素在0和1之间。是的,因为只有一个缺失的元素。)
然后你可以拿ap[0] + n * step
打印第一个不匹配的。
这是源代码(也实现了一些小的快捷方式,例如将前三行分组为一个):
def find_missing_elm_ap_series(n, series):
ap = [int(i) for i in series.split(' ')]
step = ap[1] - ap[0]
if (abs(ap[2] - ap[1]) <= abs(step)): # Check missing elt is not between 0 and 1
return ap[0] + ap[2] - ap[1]
for (i, val) in zip(range(len(ap)), ap): # And check position of missing element
if ap[0] + i * step != val:
return ap[0] + i * step
return series # missing element not found
答案 2 :(得分:1)
代码似乎正在运行。可能有一种稍微简单的方法来完成它。这是因为您不必尝试查看所有值以获得常见差异。以下代码仅查看第1个和第2个以及最后一个和第二个之间的差异。
这适用于只丢失一个值的事件(并且列表的长度至少为3)。由于值之间的最小差异将为您提供共同的差异。
def find_missing(prog):
# First we cast them to numbers.
items = [int(x) for x in prog.split()]
#Then we compare the first and second
first_to_second = items[1] - items[0]
#then we compare the last to second last
last_to_second_last = items[-1] - items[-2]
#Now we have to care about which one is closes
# to zero
if abs(first_to_second) < abs(last_to_second_last):
change = first_to_second
else:
change = last_to_second_last
#Iterate through the list. As soon as we find a gap
#that is larger than change, we fill in and return
for i in range(1, len(items)):
comp = items[i] - items[i-1]
if comp != change:
return items[i-1] + change
#There was no gap
return None
print(find_missing("1 3 5 9")) #7
print(find_missing("-1 1 3 5 9")) #7
print(find_missing("9 6 0")) #3
print(find_missing("1 2 3")) #None
前面的代码显示了这个例子。首先尝试在列表的每个值之间找到变化。然后迭代直到错过更改,并返回预期的值。
答案 3 :(得分:0)
这就是我想到的方式:找到数组元素之间最大差异的位置;然后从其他差异(差异列表中的所有相同和最小数字)重新生成序列中的预期数字:
def find_missing(a):
d = [a[i+1] - a[i] for i in range(len(a)-1)]
i = d.index(max(d))
x = min(d)
return a[0] + (i+1)*x
print find_missing([1,3,5,9,11])
7
print find_missing([1,5,7,9,11])
3
答案 4 :(得分:0)
假设第一个&amp;最后的项目不会丢失,我们也可以使用range()
或xrange()
与常见差异的步骤,完全摆脱n
,它也可以返回超过1个缺失项目(虽然不可靠取决于缺少的项目数量):
In [13]: def find_missing_elm(series):
ap = map(int, series.split())
cd = map(lambda x: x[1]-x[0], zip(ap[:-1], ap[1:]))
if len(set(cd)) == 1:
print 'complete series'
return ap
mcd = min(cd) if ap[0] < ap[1] else max(cd)
sap = set(ap)
return filter(lambda x: x not in sap, xrange(ap[0], ap[-1], mcd))
....:
In [14]: find_missing_elm('1 3 5 9 11 15')
Out[14]: [7, 13]
In [15]: find_missing_elm('15 11 9 5 3 1')
Out[15]: [13, 7]
答案 5 :(得分:0)
以下是一些想法:
以下是我提出的代码:
def find_missing_elm_ap_series(series):
ap = [int(i) for i in series.split()]
n = len(ap)
cd = {ap[i+1]-ap[i] for i in range(n-1)}
if len(cd) == 1:
print 'The series is complete'
return None
else:
common_diff = min([abs(i) for i in cd])
if ap[0] > ap[1]:
common_diff = (-1)*common_diff
return set(range(ap[0],ap[0]+common_diff*n,common_diff)).difference(set(ap)).pop()