Ktoś wysłał to pytanie tutaj kilka tygodni temu, ale wyglądało to okropnie jak praca domowa bez wcześniejszych badań, a OP szybko usunął go po otrzymaniu kilku zniżek.Obliczanie najmniejszej dodatniej liczby całkowitej nie objętej żadnym z przedziałów
Samo pytanie było jednak dość ciekawe i zastanawiałem się nad tym przez tydzień bez znalezienia satysfakcjonującego rozwiązania. Mam nadzieję, że ktoś może pomóc?
Pytanie jest następujący: podano listę odstępach liczbę całkowitą, której granice mogą dowolne wartości z 0
do N³
znajdź najmniejszą liczbę całkowitą i
i
taki sposób, że nie należą do żadnej z tych przedziałach wejściowych.
Na przykład, jeśli poda się listę [3,5] [2,8] [0,3] [10,13]
(N = 4), algorytm powinien powrócić 9
.
Najprostszym rozwiązaniem, które można myślę tras w O(n log(n))
i składa się z trzech etapów:
- Uporządkuj przerwach poprzez zwiększenie dolnej granicy
-
- Jeśli najmniejsza dolna granica wynosi> 0, return 0;
- przeciwnym przypadku wielokrotnie połączyć pierwszy interwał z drugim, do pierwszego przedziału (powiedzmy
[a, b]
) nie dotyka drugiego (powiedzmy[c, d]
) - to jest do b + 1 < C, lub aż do chwili tylko jeden przedział.
- Powrót
b + 1
To proste rozwiązanie działa w O(n log(n))
, ale oryginalny plakat napisał, że algorytm powinien działać w O(n)
. To jest trywialne, jeśli przedziały są już posortowane, ale przykład podany przez PO zawiera nieposortowane interwały. Myślę, że to musi mieć coś wspólnego z N³
związany, ale nie jestem pewien, co ... Hashing? Liniowy podział czasu? Pomysły są mile widziane.
Tutaj jest szorstka implementacja Pythona dla algorytmu opisanego powyżej:
def merge(first, second):
(a, b), (c, d) = first, second
if c <= b + 1:
return (a, max(b, d))
else:
return False
def smallest_available_integer(intervals):
# Sort in reverse order so that push/pop operations are fast
intervals.sort(reverse = True)
if (intervals == [] or intervals[-1][0] > 0):
return 0
while len(intervals) > 1:
first = intervals.pop()
second = intervals.pop()
merged = merge(first, second)
if merged:
print("Merged", first, "with", second, " -> ", merged)
intervals.append(merged)
else:
print(first, "cannot be merged with", second)
return first[1] + 1
print(smallest_available_integer([(3,5), (2,8), (0,3), (10,13)]))
wyjściowa:
Merged (0, 3) with (2, 8) -> (0, 8)
Merged (0, 8) with (3, 5) -> (0, 8)
(0, 8) cannot be merged with (10, 13)
9
Zakładam, że masz na myśli nieujemne liczby całkowite, tylko? –
Wydaje się, że jest tu błąd: "którego granice mogą przyjmować dowolne wartości od 0 do N³' (0 zamiast 1) – Vincent
" Ciągłe sortowanie według czasu? " Nie ma * nie * takiej rzeczy. Sortowanie sekwencji wartości 'n', nawet w najlepszym możliwym przypadku, zajmuje czas" O (n) ". Musisz wykonać co najmniej porównanie "n-1", aby sprawdzić, czy elementy są posortowane. – Bakuriu