Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 给定一组数字,求其中最长算术级数的长度_Python_Algorithm - Fatal编程技术网

Python 给定一组数字,求其中最长算术级数的长度

Python 给定一组数字,求其中最长算术级数的长度,python,algorithm,Python,Algorithm,我的方法如下 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]

我的方法如下
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]}
请注意:

  • 您的列表中有43个,68-43=25
  • 存在具有相同差异的多个LPA
  • 有两个错误:

  • 检查diff是否存在于
    d.keys()
    中,但不检查数字是否存在于LPA中。e、 g:当数字是43时,68 diff是25,但您当前的列表是[2,20,45]。在这种情况下,具有相同差异25的多圈
  • 您插入了
    A[j]
    ,但没有插入
    A[i]
    ,因此您只插入了68,而不是43

  • 我认为您使用的算法无法解决您想要解决的问题。 主要问题是扩展算术序列的标准没有考虑序列本身。 例如,考虑:

    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)
    

    编辑2: 请注意,可以通过分析排序项目的差异来进一步优化:

    • 计算任意两个项目之间的所有差异
    • 对于给定的差异,计算项目中有多少个元素
    • 跟踪给定项和元素的最大元素数
    • 如果对于给定的差异,项目包含的数字不能超过最大值,则跳过该选项
    • 如果元素数超过项目数的一半,则停止
    在代码中,这看起来像:

    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)
    

    对此进行基准测试(包括as
    lap\u maxprogr()
    和as
    lap\u dict()
    ,而
    lap\u combs()
    至少慢一个数量级,并且不包括在图中)表明
    lap\u diff()
    是最快的(只要输入项的数量超过大约12个):

    (全面分析)


    (请注意,
    lap_diff()
    使用了与
    lap_maxprogr()
    基本相同的方法,并进行了一些优化)。

    您必须认为,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
    

    另一种方法。将每一对视为一个进展的开始,并尝试扩展这一进展。

    重要优化:如果一个进度包含至少一半的总项目,那么它必须是最长的潜在进度

    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 最大值:开始=5,差异=5,长度=4 最大值:开始=20,差异=25,长度=3 最大值:开始=17,差异=+3,长度=2 最大值:开始=1,差异=+0,长度=10
    (代码在发布后1小时更新以修复一个小错误)

    当i=3时,您的a[i]=43,j从4到7变化。因此,在j=6时,A[j]变为68,然后差值为-25。问题在于,你的算法并不关心差异来自何处。它可以在列表中的任意两个数字之间,这不是算术级数。@JiteshMalipeddi请参见编辑2,包括基准测试