我的方法如下
1.我正在创建一个字典,用于存储所有数字对和计数之间的差异
2.键包含差异,值是一个列表。列表的第一个索引是差异出现的次数,随后的索引仅代表遵循算术级数的数字
我为此编写了以下代码
d = {}
for i in range(len(A)-1):
for j in range(i+1, len(A)):
if A[i]-A[j] in d.keys():
d[A[i]-A[j]][0] += 1
d[A[i]-A[j]].append(A[j])
else:
d[A[i]-A[j]] = [2, A[i], A[j]]
# Get the key,value pair having the max value
k,v = max(d.items(), key=lambda k: k[1])
print(v[0])
例如,如果输入为[20,1,15,3,10,5,8]
,则我的输出为4
但是,我的代码对于以下输入[83,20,17,43,52,78,68,45]
失败。
预期的结果是2,但是我得到3。当我打印字典的内容时,我发现字典中有类似
-25: [3, 20, 45, 68], -26: [3, 17, 43, 78], -35: [3, 17, 52, 78]
我不明白为什么会出现它们,因为在-25的情况下,差68和45不等于25,因此我在将值添加到字典之前进行了检查。 有人可以指出我代码中的错误吗?
我的完整输出是
{63: [2, 83, 20], 66: [2, 83, 17], 40: [2, 83, 43], 31: [2, 83, 52], 5: [2, 83, 78], 15: [2, 83, 68], 38: [2, 83, 45], 3: [2, 20, 17], -23: [2, 20, 43], -32: [2, 20, 52], -58: [2, 20, 78], -48: [2, 20, 68], -25: [3, 20, 45, 68], -26: [3, 17, 43, 78], -35: [3, 17, 52, 78], -61: [2, 17, 78], -51: [2, 17, 68], -28: [2, 17, 45], -9: [2, 43, 52], -2: [2, 43, 45], -16: [2, 52, 68], 7: [2, 52, 45], 10: [2, 78, 68], 33: [2, 78, 45], 23: [2, 68, 45]}
答案 0 :(得分:1)
我认为您使用的算法不能解决您要解决的问题。 主要问题是扩展算术序列的标准未考虑序列本身。 考虑例如:
A = [10, 20, 50, 60]
存在两个属于差异-10
的序列,因此dict
实际上不是一个很好的数据结构,不能以您的算法为基础,至少不是您打算的方式。
您可以通过多种方式解决问题。 一种非常直接但不是非常有效的方法是:
在此代码中,如下所示:
import itertools
def is_arithmetic_progression(items):
diffs = [x - y for x, y in zip(items[1:], items[:-1])]
return diffs[1:] == diffs[:-1]
def skip_items(items, indexes):
return [item for i, item in enumerate(items) if i not in indexes]
def lap_combs(items, sorting=True):
if sorting:
items = sorted(items)
for i in range(len(items)):
for indexes in itertools.combinations(range(len(items)), i):
new_items = skip_items(items, indexes)
if is_arithmetic_progression(new_items, False):
return new_items
items = [83, 20, 17, 43, 52, 78, 68, 45]
longest_ap = lap_combs(items)
print(longest_ap)
# [78, 83]
items = [83, 20, 17, 43, 52, 78, 68, 45, 70]
longest_ap = lap_combs(items)
print(longest_ap)
# [20, 45, 70]
请注意,可以通过分析排序项目的差异来进一步优化:
在代码中,它看起来像:
def seed_diff_len_to_seq(seed, diff, length):
return [seed + diff * k for k in range(length)]
def lap_diffs(items):
half_len_items = len(items) // 2
span = max(items) - min(items)
seed = 0
max_seq_len = 0
diff = None
set_items = set(items)
for item_i, item_j in itertools.combinations(sorted(items), 2):
diff_ji = item_j - item_i
if diff_ji == 0:
seq_len = sum(1 for item in items if item == item_i)
elif abs(diff_ji * max_seq_len) > span:
continue
else:
seq_len = 2
while item_i + diff_ji * seq_len in set_items:
seq_len += 1
if seq_len > max_seq_len:
max_seq_len = seq_len
seed = item_i
diff = diff_ji
if seq_len > half_len_items:
break
return seed_diff_len_to_seq(seed, diff, max_seq_len)
对此进行基准化(包括将@VPfB's solution标记为lap_maxprogr()
,将@rusu_ro1's solution标记为lap_dict()
,而lap_combs()
至少慢1个数量级,并且不包含在图)显示lap_diffs()
是最快的(输入的项目数超过大约一打之后):
(全面分析here。)
(请注意,lap_diffs()
使用与lap_maxprogr()
基本上相同的方法,但有更多优化)。
答案 1 :(得分:0)
注意:
有2个错误:
d.keys()
中是否存在差异,但是不检查数字是否在LPA中。例如:当数字为43时,68 diff为25,但当前列表为[2,20,45]。在这种情况下,存在多个具有相同差异25的LAP。A[j]
,但没有插入A[i]
,因此您只插入了68,而不是43 答案 2 :(得分:0)
您必须认为btw数之差不足以作为关键,例如8-3 = 5,也5-0 = 5
您可以尝试:
def length_longest_AP(A):
d = {}
A.sort()
for index_i, i in enumerate(A[:-1]):
for index, j in enumerate(A[index_i + 1 :]):
dif = j - i
key = f'{i}_{index_i}_{dif}'
if key in d:
continue
d[key] = [i, j]
possible_next = j + dif
try:
current_index = index_i + 1 + index
possible_next_one_index = current_index + A[current_index + 1:].index(possible_next)
# avoiding repetitions
if current_index == possible_next_one_index:
possible_next_one_index = current_index + 1
except ValueError:
continue
while True:
d[key].append(possible_next)
possible_next += dif
try:
current_index = possible_next_one_index
possible_next_one_index = current_index + A[current_index + 1:].index(possible_next)
# avoiding repetitions
if current_index == possible_next_one_index:
possible_next_one_index = current_index + 1
except ValueError:
break
return len(max(d.values(), key=len))
print(length_longest_AP([20,1,15,3,10,5,8]))
print(length_longest_AP([1,1,1,1,1,1,1,1,1,1]))
print(length_longest_AP([83,20,17,43,52,78,68,45]))
输出:
4
10
2
答案 3 :(得分:0)
另一种方法。将每对视为进展的开始,并尝试扩展该进展。
重要的优化:如果进度至少包含项目总数的一半,则它必须是最长的进度。
import itertools
def maxprogr(items):
# 2 or more numbers required to find any progression
# if there are multiple maximums, the first one is returned
half = len(items) / 2
pmax = (None, None, 0)
for start, stop in itertools.combinations(sorted(items), 2):
diff = stop - start
if diff == 0:
plen = sum(1 for x in items if x == start)
else:
plen = 2
while start + diff*plen in items:
plen += 1
if plen > pmax[2]:
pmax = (start, diff, plen)
if plen > half:
break
return pmax
# and some tests:
def print_maxprogr(items):
print("MAX: start={0[0]}, diff=+{0[1]}, len={0[2]}".format(maxprogr(items)))
test1 = [20,1,15,3,10,5,8]
print_maxprogr(test1)
test2 = [83, 20, 17, 43, 52, 78, 68, 45, 70]
print_maxprogr(test2)
test3 = [83, 20, 17, 43, 52, 78, 68, 45]
print_maxprogr(test3)
test4 = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
print_maxprogr(test4)
测试输出:
MAX: start=5, diff=+5, len=4 MAX: start=20, diff=+25, len=3 MAX: start=17, diff=+3, len=2 MAX: start=1, diff=+0, len=10
(发布后1小时更新了代码,以解决小错误)