2010-12-07 3 views
1

Python 집합에서 N 개의 연속적인 정수 중 가장 작은 정수의 목록을 얻는 가장 좋은 방법은 무엇입니까?Python 집합에서 가장 작은 연속 정수 찾기

>>> s=set([5,6,10,12,13,15,30,40,41,42,43,44,55,56,90,300,500]) 
>>> s 
set([42, 43, 44, 5, 6, 90, 300, 30, 10, 12, 13, 55, 56, 15, 500, 40, 41]) 
>>> smallest_contiguous(s,5) 
[40,41,42,43,44] 
>>> smallest_contiguous(s,6) 
[] 

편집 : 답변 해 주셔서 감사합니다.

+3

종류에 때문에 호출의 알고리즘은 O (N logn) 여기 모든 고된 작업을 수행하고 n 개의 항목을 1로 DIFF를 확인합니다. – khachik

+0

숙제에 문제가 있습니까? – troynt

답변

3

스벤 올바른 생각을 가지고있다. 먼저 N - 1 번 번호 만 확인하면 수퍼 셋을 확인하지 않아도됩니다.

def smallest_contiguous(s, N): 
    lst = list(s) 
    lst.sort() 
    Nm = N-1 
    for i in xrange(len(lst) - Nm): 
     if lst[i] + Nm == lst[i + Nm]: 
      return range(lst[i], lst[i]+N) 
    return [] 

이것은 세트가 정수로만 구성된다는 것을 알고 입력 세트로 항상 올 바릅니다.

+0

Nice :)'xrange (len (lst) - Nm) 여야합니다. '라고 생각합니다. –

+0

@ 스벤, 당신 말이 맞아요. 좋은 발견. –

2

어때?

def smallest_contiguous(s, N): 
    lst = sorted(s) 
    for i in lst: 
     t = range(i, i+N) 
     if s.issuperset(t): 
      return t 
    return [] 

가장 효율적인 솔루션은 아니지만 간결합니다.

편집 : 저스틴의 접근 방식은 또한 더 간결하게 할 수있다 :

def smallest_contiguous(s, N): 
    lst = sorted(s) 
    for a, b in zip(lst, lst[N - 1:]): 
     if b - a == N - 1: 
      return range(a, b + 1) 
    return [] 
2

그렇게해야합니다 ... 미리 정렬 된 목록에서 length - 1 단계를 찾으십시오. 정수 만 포함하고 정렬되므로 차이는 length - 1이어야합니다.

def smallest_contiguous(s,N): 
    try: 
     result = [] 
     while len(result) < N: 
      min_value = min(s) 
      s.remove(min_value) 
      if result == [] or min_value == result[-1] + 1: 
       result.append(min_value) 
      else: 
       result = [min_value] 
     return result 
    except ValueError: 
     return [] 

그것은 부작용으로 설정 입력을 수정합니다

def smallest_contiguous(myset, length): 
    if len(myset) < length: 
     return [] 

    s = sorted(myset) 
    for idx in range(0, len(myset) - length + 1): 
     if s[idx+length-1] - s[idx] == length - 1: 
      return s[idx:idx+length] 

    return [] 

s=set([5,6,10,12,13,15,30,40,41,42,43,44,55,56,90,300,500]) 
print smallest_contiguous(s, 5) 
print smallest_contiguous(s, 6) 
+0

이 코드는 저스틴의 원래 코드와 동일한 off-by-one 오류가 있습니다. 'idx 범위 (0, len (myset) - 길이 + 1)'이어야합니다. –

+0

네 말이 맞아. 편집 됨. 코드에 너무 많은 +/- 1이 있습니다 ... 이제 한 번 더. –

0

는 여기에 내가 생각 해낸 하나입니다.

+0

이것은 각 반복에서 남은 세트 전체를 반복하므로 O (n^2)입니다. 물론 작동합니다. –

+0

@ 스벤, 무슨 뜻인지 모르겠다. 충분한 길이의 연속 블록을 찾으면 중지됩니다. – user483263

+0

네, 정상적으로 작동합니다. 나는 알고리즘의 복잡성에 대해 얘기하고있다. (http://en.wikipedia.org/wiki/Algorithmic_complexity) : 큰 세트의 경우,이 알고리즘은 다른 어떤 것보다 훨씬 효율적이지 못하다. –

0

구조로 itertools. GROUPBY는 sorted()

>>> from itertools import groupby, count 
>>> def smallest_contiguous(s, N): 
...  for i,j in groupby(sorted(s), key=lambda i,c=count().next: i-c()): 
...   res = list(j) 
...   if len(res) == N: 
...    return res 
...  return [] 

... 
>>> smallest_contiguous(s,5) 
[40, 41, 42, 43, 44] 
>>> smallest_contiguous(s,6) 
[] 
0
def smallest_contiguous(s, n): 
    xs = sorted(s) 
    return next(x for i, x in enumerate(xs) if xs[i + n - 1] == x + n - 1) 
관련 문제