查找不在间隔列表中的最小数字

时间:2019-05-13 08:45:21

标签: python intervals

我必须找到不在间隔列表中的最小数字。例如,我有一个列表:[(2,6),(0,3),(9,10)]。我必须通过检查从0到10的所有数字来找到最小的数字,直到找到不在这些范围内的最小数字为止。 因此,数字不能介于2到6(包括两者),0和3、9和10之间。

我写了一个函数,但我找不到正确的答案。我总是得到程序检查的所有第一个数字,但我只需要最后一个数字。 而且我不明白为什么它不能与return一起使用。

intervals = [(2, 6), (0, 3), (9, 10)]
def smallest_number(intervals):
   i = 0
   while True:
      for first, second in intervals:
         if i in range(first, second + 1):
            i += 1
            print(i)

print(smallest_number(intervals))

我希望输出7,但是我会得到一个7的循环或从1到7的数字,具体取决于我将print(i)放在哪里。

6 个答案:

答案 0 :(得分:2)

这是一种方法:

from itertools import chain
intervals = [(2, 6), (0, 3), (9, 10)]

ranges = chain.from_iterable(range(i, j+1) for i, j in l)
min(set(range(10)).difference(ranges))
# 7

详细信息

第一步,使用生成器理解并使用每个range中的两个元素调用tuple,从元组中包含的范围中创建一个set。使用itertools.chain将结果展平:

ranges = chain.from_iterable(range(i, j+1) for i, j in l)
print(list(ranges))
# {0, 1, 2, 3, 4, 5, 6, 9, 10}

现在,我们只需要寻找该集合与rangen之间的差异的min

diff = set(range(10)).difference(ranges)
# {7, 8}

答案 1 :(得分:0)

我没有要检查的Python,但是看来您的函数未返回任何内容,因此print(smallest_number(intervals))打印None

def smallest_number(intervals):
   i = 0
   while True:
      for first, second in intervals:
      if i in range(first, second + 1):
          i += 1
      else:
          return i

现在print(smallest_number(intervals))应该可以工作了。

答案 2 :(得分:0)

您的代码将在无限循环中结束之前,打印间隔中的所有 数字,而不是不是的数字。试试这个:

def smallest_number(intervals):
    i = 0
    while True:
        for first, second in intervals:
            if i in range(first, second + 1):
                i += 1
                break # break from inner loop
        else:
            break # break from outer loop
    return i # return number

此外,尽管在Python 3中if i in range(first, second + 1):没问题(而且很快),但我还是建议使用if first <= i <= second:

或更短,使用nextany

def smallest_number(intervals, max_ = 10):
    return next((i for i in range(max_ + 1)
                 if not any(first <= i <= second for first, second in intervals)),
                None) # None is default if none is found

答案 3 :(得分:0)

我的解决方案可以保护没有最小数量的情况。

checking = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
intervals = [(2, 6), (0, 3), (9, 10)]
min_number = None

unique = set()
for left, right in intervals:
    unique.update(range(left, right + 1))

subset = set(checking) - unique
if subset:
    min_number = min(subset)

print(min_number)

答案 4 :(得分:0)

如果您想要一个允许的数字列表,而不仅仅是最小的数字,这可能是一个不错的选择。

import itertools


def flatten(list_of_sublists):
    return itertools.chain.from_iterable(list_of_sublists)


def excluded_numbers(intervals):
    excluded_ranges = [range(lower, upper + 1) for lower, upper in intervals]
    excluded_numbers = set(flatten(excluded_ranges))
    return excluded_numbers


def permitted_numbers(intervals):
    excluded = excluded_numbers(intervals)
    max_excluded = max(excluded)
    candidates = set(range(max_excluded + 2))
    return candidates - excluded


def smallest_number(intervals):
    return min(permitted_numbers(intervals))

答案 5 :(得分:0)

按时间间隔的起点(如果起点相等,则按终点)排序。然后从第一个间隔开始,并继续向右扩展边界,直到下一个间隔的起点大于我们当前的覆盖范围终点为止。

Take (2,6),(0,3),(9,10)
Sorting: (0,3),(2,6),(9,10)
current coverage = [0,3]

由于3 <6和2 <3,我们可以将正确的点增加到6 因此覆盖率变为[0,6] 但是6 <9,所以7是最小的数字,它不在任何间隔中。另外,您还需要检查第一个间隔的起点是否大于0。在这种情况下,答案将为0。