Mam problem z algorytmem.
Biorąc pod uwagę macierz (lub zestaw) o nieujemne liczby całkowite. Znajdź maksymalny zestaw z tak że dla wszystkich ,.
Na przykład:
- Jeśli = [1, 3, 4, 1, 3, 6], wówczas może być [3, 3, 6] lub [3, 4, 6] lub [4, 3, 6].
- W = [7, 5, 1, 1, 7, 4], wówczas wynosi [7, 5, 7, 4].
Próbowałem tej funkcji rekurencyjnej.
function(T):
if minimum(T) >= length(T):
return T
else:
return function(T\minimum(T))
Czy istnieje jakiś algorytm nierekurencyjny. (Nie sprawdziłem mojego algorytmu rekurencyjnego, więc może mieć pewną wadę).
algorithms
optimization
sets
drzbir
źródło
źródło
Z mojego komentarza pierwotnie: Jest to ściśle związane z wszechobecnym ilość w akademickiego oceny produktywności, indeks Hirsh, lepiej znany jako -indexh . W skrócie jest zdefiniowany jako liczba publikacji ma się tak, że każdy z nich ma co najmniej h cytowań (największy taki h ).h h h
Twój problem różni się tylko tym, że interesowałbyś się nie tylko liczbą publikacji spełniających to kryterium, ale także liczbą ich cytowań , ale to banalna modyfikacja. Dane już tam są, oryginalny algorytm po prostu je upuszcza.
Ogólnie stosowane obliczenia są dość proste i zgadzają się z odpowiedzią Karolis Juodelė .
Aktualizacja: W zależności od wielkości i charakteru danych warto zbadać metody, które częściowo sortują tablicę, filtrując dane powyżej i poniżej punktu kluczowego (przychodzi na myśl szybkie sortowanie). Następnie w zależności od tego, czy jest za mało, czy za dużo, dostosuj oś obrotu i ponów w podzbiorze, który ją zawiera i tak dalej. Nie potrzebujesz kolejności między elementami wyższymi niż , a na pewno nie między tymi niższymi. Na przykład, gdy znajdziesz wszystkie elementy większe lub równe h 1 i jest ich mniej niż h 1 , nie musisz ponownie dotykać tego podzbioru, po prostu dodaj go. Konwertuje to rekurencję związaną z Quicksort na rekurencję ogona, a zatem może być przepisana jako pętla.h h1 h1
Mój Haskell jest trochę zardzewiały, ale powinno to zrobić to, co opisałem powyżej i wydaje się działać. Mam nadzieję, że do pewnego stopnia można to zrozumieć, chętnie udzielę dalszych wyjaśnień.
Chodzi o to, aby zebraćremaining/2
granted
to, co wiesz, na pewno będzie uczestniczyć w wyniku, a nie sortować go dalej. Jeśligreater
razem zx
pasowaniem mamy szczęście, w przeciwnym razie musimy spróbować z mniejszym podzbiorem. (Czopx
jest po prostu cokolwiek stało się pierwsza pozycja w podmenu, który jest aktualnie rozpatrywana.) Należy zauważyć, że znacząca zaleta przed sobą największe elementy jeden po drugim jest to, że robimy to na blokach średniej wielkości i nie trzeba ich dalej sortować.Przykład:
Weźmy twój zestaw
[1,3,4,1,3,6]
.x = 1
,granted = []
,greater = [3,4,1,3,6]
. Ojej, trafiliśmy na przypadek patologiczny, gdy oś jest za mała (właściwie tak mała, żesmaller
jest pusta) już na pierwszym etapie. Na szczęście nasze algo jest na to gotowe. Odrzucax
i próbuje ponowniegreater
sam.x = 3
,granted = []
,greater = [4,3,6]
. Razem tworzą tablicę o długości 4, ale ograniczamy ją tylko od dołu o 3, więc to za dużo. Powtórzgreater
sam.x = 4
,granted = []
,greater = [6]
. Daje to tablicę zawierającą 2 elementy ≥ 4 każdy, wydaje się, że moglibyśmy użyć trochę więcej. Zachowaj to i powtarzaj dalejsmaller = [3]
.x = 3
,granted = [4,6]
,greater = []
. To razem daje tablicę 3 elementów ≥ 3 każdy, więc mamy nasze rozwiązanie[3,4,6]
i możemy wrócić. (Pamiętaj, że permutacja może się różnić w zależności od kolejności wprowadzania danych, ale zawsze będzie zawierać najwyższe możliwe warunki, nigdy[3,3,6]
lub[3,3,4]
w twoim przykładzie).(Przy okazji zauważmy, że rekurencja rzeczywiście po prostu zapadła się w cykl.) Złożoność jest nieco lepsza niż szybkie sortowanie z powodu wielu zapisanych porównań:
W powyższym kodzie znajduje się kilka niepotrzebnych porównań, takich jak obliczenie,
smaller
czy jest to potrzebne, czy nie, można je łatwo usunąć. (Myślę, że leniwa ocena to załatwi.)źródło
Nie ma nic złego w twoim algorytmie i oczywiście większość algorytmów rekurencyjnych można przekształcić w pętle, tutaj wersja pętli twojego kodu rekurencyjnego:
źródło
Każdy algorytm rekurencyjny można przepisać, aby użyć iteracji. W końcu maszyna Turinga nic nie wie o rekurencji, ale może zaimplementować dowolny algorytm. Zasadniczo możesz przepisać swoją funkcję rekurencyjną, pisząc własny kod manipulacji stosem, aby zapamiętać wartości parametrów funkcji i wszelkich lokalnych zmiennych, które może mieć. W tym konkretnym przypadku twoja funkcja jest rekurencyjna (po powrocie wywołania rekurencyjnego wraca też rzecz, która go wywołała), więc nie musisz nawet utrzymywać stosu.
źródło
Użyj mini-sterty, aby wykonać częściowy rozsypisko, ponieważ nie potrzebujesz sortować całej tablicy.
Trzymaj łapczywie elementy, dopóki nie przekroczysz podanego progu.
źródło