Przechowuj największe liczby 5000 ze strumienia liczb

Biorąc pod uwagę następujący problem:

"przechowuj największe 5000 liczb ze strumienia liczb"

Rozwiązaniem, które przychodzi na myśl, jest binarne drzewo wyszukiwania utrzymujące liczbę węzłów w drzewie i odniesienie do najmniejszego węzła, gdy liczba osiągnie 5000. Gdy liczba osiągnie 5000, każda nowa Liczba do dodania może być porównana z najmniejszym elementem w drzewie. Jeżeli jest większa, można dodać nową liczbę, wtedy najmniejsza usunięta i nowa najmniejszy obliczony (który powinien być bardzo prosty już mając poprzedni najmniejszy).

Mój problem z tym rozwiązaniem polega na tym, że drzewo binarne naturalnie zostanie wypaczone (ponieważ usuwam tylko z jednej strony).

Czy istnieje sposób na rozwiązanie tego problemu, który nie stworzy strasznie przekrzywionego drzewa?

W razie gdyby ktoś chciał, umieściłem pseudo-kod dla mojego rozwiązania do tej pory poniżej:

process(number)
{
  if (count == 5000 && number > smallest.Value)
  {
    addNode( root, number)
    smallest = deleteNodeAndGetNewSmallest ( root, smallest)
  }
}

deleteNodeAndGetNewSmallest( lastSmallest)
{
  if ( lastSmallest has parent)
  {
    if ( lastSmallest has right child)
    {
      smallest = getMin(lastSmallest.right)
      lastSmallest.parent.right = lastSmallest.right
    }
    else
    {
      smallest = lastSmallest.parent
    }
  }
  else 
  {
    smallest = getMin(lastSmallest.right)
    root = lastSmallest.right
  }
  count--
  return smallest
}

getMin( node)
{
  if (node has left)
    return getMin(node.left)
  else
    return node
}

add(number)
{
  //standard implementation of add for BST
  count++
}
Author: Richard, 2012-05-25

2 answers

Najprostszym rozwiązaniem jest utrzymanie sterty min o maksymalnym rozmiarze 5000.

  • za każdym razem, gdy pojawia się nowa liczba-sprawdź, czy sterta jest mniejsza, a następnie 5000, jeśli tak-dodaj.
  • Jeśli nie jest-sprawdź, czy minimum jest mniejsze, to nowe element, a jeśli tak, to wyskakuj i wstaw nowy element.
  • kiedy skończysz-masz stertę zawierającą 5000 największych elementów.

Rozwiązanie to jest O(nlogk) złożonością, gdzie n jest liczba elementów i k jest liczbą elementów, których potrzebujesz (5000 w Twoim przypadku).

Można to zrobić również w O(n)za pomocą algorytmu wyboru - zapisz wszystkie elementy, a następnie znajdź 5001-ty największy element i zwróć wszystko większe od niego. Ale to jest trudniejsze do wdrożenia i dla rozsądnej wielkości Wejścia-może nie być lepiej. Ponadto, jeśli stream zawiera duplikaty, potrzebne jest więcej przetwarzania.

 37
Author: amit,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-13 16:43:59

Użyj (minimalnej) kolejki priorytetów. Dodaj każdy przychodzący element do kolejki i gdy rozmiar osiągnie 5000 Usuń minimalny (górny) element za każdym razem, gdy dodasz przychodzący element. Kolejka będzie zawierać 5000 największych elementów, a gdy wejście się zatrzyma, po prostu usuń zawartość. Ten MinPQ jest również nazywany stertą, ale jest to termin przeciążony. Wstawianie i usuwanie zajmuje około log2(N). Gdzie n ma wartość 5000, to byłoby nieco ponad 12 [log2(4096) = 12] razy więcej pozycji niż przetwarzam.

Doskonałym źródłem informacji są algorytmy, (IV edycja) autorstwa Roberta Sedgewicka i Kevina Wayne ' a. Jest doskonałe MOOC na coursera.org na podstawie tego tekstu.

 1
Author: user1295785,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-01 16:31:03