算法和 运行-时间分析

algorithms and run-time analysis

一个文件(包括两个例子)是一个禁止号码区间的列表。例如,包含 12-18 的行表示禁止使用 12 到(含)18 的所有数字。间隔可能重叠。 我们想知道最小值是多少。 使用变量分析运行-时间(不一定需要全部):

• N:最大(不是允许的最大)数量;所以数字在 0 和 N

之间

• K:文件中的间隔数

• M:最大区间宽度。

一个。有一个明显的方法可以解决这个问题:我们正在检查所有数字,直到我们 运行 进入允许的最小值。 • 这种算法有多快?

乙。您或许可以想象另一种使用 N 字节(或位)内存的简单算法。 (提示:删除线。) • 用文字描述。例如,您可以进行自己的分配(比如一些介于 0 和 20 之间的数字间隔),并在其上显示算法。但是,它也起草了一般说明。 • 这个算法有多快?思考时,用N、K、M(如果你需要的话)。

C。做一个不额外消耗内存的算法(更准确的说:内存消耗应该与N、K、M无关),但是比A点下的算法要快。 • 形容它。 • 它有多快?是不是比B算法快?

D.现在我们感兴趣的是允许有多少个数字(0 到 N 之间)。对于这个问题,您将如何调整上述算法?他们的费率会怎样?

file = "0-19.txt"
intervals = [tuple(map(int, v.split("-"))) for v in open(file)]
#example# intervals = [(12, 18), (2, 5), (3, 8), (0, 4), (15, 19), (6, 9), (13, 17), (4, 8)]#

我当前的代码只是执行程序,但我还没有想出更好的代码算法,仍然需要大量工作才能理解,我需要一个快速解决方案 code/algorithm 例如 A、B、和C,也许还有D。然后我可以自己研究时间分析。感谢帮助!

def generator_intervala(start, stop, step):
    forbidden_numbers = set()
    while start <= stop:
        forbidden_numbers.add(start)
        start += step
    return (forbidden_numbers)


mnozica = set()
for interval in intervals:
    a, b = interval
    values = (generator_intervala(a, b, 1))
    for i in values:
        mnozica.add(i)



allowed_numbers = set()
N = max(mnozica)
for i in range(N):
    if i not in mnozica:
        allowed_numbers.add(i)




print(intervals)
print(mnozica)
print(min(allowed_numbers))
print(max(mnozica))

Output:

[(12, 18), (2, 5), (3, 8), (0, 4), (15, 19), (6, 9), (13, 17), (4, 8)]
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 12, 13, 14, 15, 16, 17, 18, 19}
10
19

您设置的方法不必要地复杂:

N = 100
ranges = [(12, 18), (2, 5), (3, 8), (0, 4), (15, 19), (6, 9), (13, 17), (4, 8)]

do_not_use = set()

for (a,b) in ranges: 
    do_not_use.update(range(a,b+1))          

print(do_not_use)  

print( min(a for a in range(N+1) if a not in do_not_use))

几乎是所有需要的。输出:

set([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 12, 13, 14, 15, 16, 17, 18, 19])
10

这与 N 无关,它只取决于范围内有多少数字。

仅在集合中存储禁止数字需要 O(1) 进行检查,使用范围内的 min() 构建来获得最小值。

如果先对元组进行排序,然后对它们进行迭代,直到找到第一个间隙,排序时为 Θ(N log N),然后为搜索时为 Θ(N):

def findme():
    ranges = [(12, 18), (2, 5), (3, 8), (0, 4), (15, 19), (6, 9), (13, 17), (4, 8)]
    ranges.sort()  # inplace sort, no additional space requirements
    if ranges[0][0]>0: 
        return 0

    for ((a_min,a_max),(b_min,b_max)) in zip(ranges,ranges[1:]):
        if a_max < b_min-1:
            return a_max+1

    return ranges[-1][1]+1  # might give you N+1 if no solution in 0-N exists

timeit 你的 vs 我的:

您的代码使用了 2 个集合,以及多个循环,增量添加到您的集合和函数调用中使其变慢:

N = 100

def findme():
    ranges = [(12, 18), (2, 5), (3, 8), (0, 4), (15, 19), (6, 9), (13, 17), (4, 8)]
    ranges.sort()
    if ranges[0][0]>0: 
        return 0

    for ((a_min,a_max),(b_min,b_max)) in zip(ranges,ranges[1:]):
        if a_max < b_min-1:
            return a_max+1

    return ranges[-1][1]+1

def mine():
    ranges = [(12, 18), (2, 5), (3, 8), (0, 4), (15, 19), (6, 9), (13, 17), (4, 8)]
    N = 100
    do_not_use = set()

    for (a,b) in ranges: 
        do_not_use.update(range(a,b+1))          

    return min(a for a in range(N+1) if a not in do_not_use)

def yours():
    ranges = [(12, 18), (2, 5), (3, 8), (0, 4), (15, 19), (6, 9), (13, 17), (4, 8)]
    def generator_intervala(start, stop, step):
        forbidden_numbers = set()
        while start <= stop:
            forbidden_numbers.add(start)
            start += step
        return (forbidden_numbers)

    mnozica = set()
    for interval in ranges:
        a, b = interval
        values = (generator_intervala(a, b, 1))
        for i in values:
            mnozica.add(i)

    allowed_numbers = set()
    N = max(mnozica)
    for i in range(N):
        if i not in mnozica:
            allowed_numbers.add(i)

    return min(allowed_numbers)

import timeit
print("yours", timeit.timeit(yours,number=100000))  
print("mine", timeit.timeit(mine,number=100000))
print("findme", timeit.timeit(findme,number=100000))

输出:

yours 1.3931225209998956
mine 1.263602267999886
findme 0.1711935210005322