【问题标题】:Function that fills in missing numbers to create complete sequence填充缺失数字以创建完整序列的功能
【发布时间】:2020-07-17 05:15:46
【问题描述】:

我正在尝试创建一个函数来填充列表中两个数字之间的任何缺失数字。原始列表必须更改,不能是新列表。

例如:[13,15,20] 将返回 [13,14,15,16,17,18,19,20]。

请注意,我不能使用范围函数。

这是我的代码:

def complete(list1):
    i= 0
    if len(list1) > 1:
        for number in list1:
           if number - list1[i+1] != -1:
               number += 1
               list1.insert(i + 1, number)
           i += 1
        return list1
    else:
        return list1

我收到“列表索引超出范围”错误。

【问题讨论】:

    标签: python-3.x list for-loop if-statement


    【解决方案1】:

    这是您的错误的来源:

    ...
    for number in list1:
        if number - list1[i+1] != -1:
            ...
        i += 1
    

    基本上,当i+1 让您越界并且您没有采取任何措施阻止这种情况发生时,就会出现一个点(该点是list1 中的最后一个number)。索引就像那样很棘手,所以我想提供一种无索引(嗯,几乎)的方法。顺便说一句,从您的评论到 Bonfire 的回答,我看到任务是就地更改原始列表。虽然如今变异参数被认为是一种非常糟糕的编码实践,但这是一种相对有效的方法:

    import typing as t
    
    def complete_sequence(partial: t.List[int]) -> t.List[int]:
        # edge case
        if len(partial) < 2:
            return partial
        # a lookup table for numbers we already have
        observed = set(partial)
        # append numbers we don't have
        start = partial[0]
        stop = partial[-1]
        num = start + 1
        while num < stop:
            if not num in observed:
                partial.append(num)
            num += 1
        # in-place sort
        partial.sort()
        return partial
    

    如您所见,我们可以简单地附加所有内容(每次插入 O(1))并排序,而不是在现有数字之间插入值(每次插入花费 O(n) 时间)。这不仅简化了逻辑(我们不再需要跟踪那些讨厌的索引),而且还将计算时间复杂度从 O(n^2) 降低到 O(n*log(n))。

    【讨论】:

    • 您好,非常感谢您的意见。但是,由于这是一个针对所有 Python 初学者的问题,我认为您的代码可能太高级了。
    • @ccxy 这个答案是你作为初学者应该学习的答案。
    • 记好!谢谢你的建议:)
    • @ccxy 我不同意您对哪种解决方案或多或少先进的看法。从我的角度来看,复杂的索引逻辑比我回答中相当简单的方法需要更多的技能。
    • 嗨 Eli,我收到了导师对这两个代码的反馈(我简化了 Bonfire 的代码),虽然你的代码更简单,但我的导师鼓励我在这个案例中使用索引逻辑,只是为了让我们更好地理解它是如何工作的,部分原因在于我们目前还没有接触到导入概念、set() 和 sort() 函数。为了 SO 社区的未来利益,我已将您的答案标记为绿色,该答案具有更简单的方法。再次感谢您的想法! :)
    【解决方案2】:

    为了实现你想做的,我对逻辑做了一些改动:

    def complete(list1):
        if len(list1) < 2 : return list1
    
        num = list1[0]
        i = -1
    
        while num < list1[-1]:
            num += 1
            i += 1
    
            if num in list1: continue
    
            if i < len(list1) - 1:
                list1.insert(i + 1, num)
            else:
                list1.append(num)
    
        return list1
    
    print(complete([13, 14, 20]))
    #  [13, 14, 15, 16, 17, 18, 19, 20]
    
    print(complete([13, 14, 15]))
    #  [13, 14, 15]
    

    【讨论】:

    • 您好,我忘了说原始列表必须更改,不能是新的。我已经编辑了问题。
    • 我会看看我能做什么。
    • 嗨,Bonfire,我将绿勾更改为 Eli 的答案,只是为了为 SO 社区提供更直接的替代方案以供将来参考。澄清一下,这个行为绝不是不赞成你的回答,事实上,你的回答有很大的帮助,我已经使用你的索引逻辑思想来进一步即兴我的代码。我希望你能理解我的理由,非常感谢你的想法! :) -真诚的 ccxy-
    • 我理解你的理由,我对此没有任何问题。不用道歉!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-10-06
    • 2021-09-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-16
    相关资源
    最近更新 更多