• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Optymalizacja algorytmu

Aruba Cloud VPS - 50% taniej przez 3 miesiące!
0 głosów
909 wizyt
pytanie zadane 2 grudnia 2017 w Python przez nastrand Nowicjusz (150 p.)

Czesc wszystkim,

Mam problem z zadaniem z algorytmow. Zadanie sklada sie z dwoch czesci:

1. Majac liste liczb calkowitych gdzie kazda liczba moze pojawic sie wiele razy nalezy zidentyfikowac liczbe wystepujaca najrzadziej. Jesli kilka roznych liczb wystepuje z taka sama frekwencja, program powinien zwrocic liczbe o najwyzszym indeksie. Przykladowo z listy [1,2,2,1] algorytm musi zwrocic 1. Lista jest nieuporzadkowana.

Ta czesc nie stanowi problemu. Moj algorytm napisany w Python wyglada tak:

def leastCommon(someList):
    element = someList[0]
    counter = someList.count(element)
    # counter inicjuje zmienna stanowiaca poczatkowy punkt odniesienia 
    for i in someList:
        # petla liczy czestotliwosc wystepowania
        # kazdego elementu na liscie i zapisuje
        # w zmiennej least liczbe o najnizszej frekwencji
        if someList.count(i) <= counter:
            counter = someList.count(i)
            least = i
    return least

   Problemem jest natomiast druga czesc zadania:

2. Majac uporzadkowana w kolejnosci rosnacej liste liczb calkowitych, zoptymalizuj wczesniejszy algorytm. Optymalizacja musi uwzgledniac strukture nowej listy (uporzadkowana w kolejnosci rosnacej).

W zadaniu nie wolno uzyc slownikow ani zadnych bibliotek Pythona.

Pierwszy algorytm ma zlozonosc O(n²). Zeby ulepszyc drugi algorytm, musialby miec zlozonosc O(n), O(log n) albo O(n log n). Niestety doznalem jakiejs blokady umyslowej i nie jestem w stanie zrobic drugiej czesci zadania. Walkuje to od tygodnia i potrzebuje swiezego spojrzenia. Nie chodzi mi o gotowe rozwiazanie, a raczej pokierowanie we wlasciwym kierunku. Bede bardzo wdzieczny za wszelka pomoc.

M.

1 odpowiedź

+2 głosów
odpowiedź 2 grudnia 2017 przez Schizohatter Nałogowiec (39,600 p.)
wybrane 2 grudnia 2017 przez nastrand
 
Najlepsza
Po prostu przeleć tę pętlę i dodawaj += 1 przy każdej iteracji. W momencie zmiany liczby (są uporządkowane), zapisz wynik i zresetuj licznik. Przy następnej zmianie liczby sprawdź, czy ten "counter" osiągnął mniejszą wartość niż poprzedni. Jeśli tak, to go zapisz i kontynuuj.

 

EDIT:

Próbowałem to napisać sobie i jest mały problem z edge-case'ami, ale szedłbym w tę stronę. Edge-case to taki, że najmniejszą częstość posiada liczba ostatnia i jest tylko jedna. Obszedłem go w taki sposób, że dodałem na końcu tablicy nulla, żeby zrobić jeszcze jedną iterację. https://paste.ofcode.org/bxAndi7e2XW8rmDGDKWyVb. Ba, wykonanie tej jeszcze jednej iteracji jest niezbędne :P
komentarz 2 grudnia 2017 przez nastrand Nowicjusz (150 p.)
Dzieki za pomoc. Za bardzo skupilem sie na probie optymalizacji do O(n log n) i oddalilem sie od bardziej oczywistych rozwiazan. Twoj kod przelozony na Pythona dziala doskonale.

Dzieki i pozdrawiam!
komentarz 2 grudnia 2017 przez Schizohatter Nałogowiec (39,600 p.)
Proszę, pozdrawiam.

Nota bene nie wiem, jaką złożonością cieszy się mój algorytm, ale chyba to będzie n+1. Nie mam pojęcia, jak się takie coś liczy. Ale zakładam, że skoro wywołaliśmy pętlę n + 1 razy, to można to pobić tylko wywołując ją n-razy, lub posiadając więcej informacji na temat zbioru danych.
komentarz 2 grudnia 2017 przez nastrand Nowicjusz (150 p.)
Zgadza sie, Twoj algorytm ma zlozonosc O(n) (jedynka jest zbedna). Moj algorytm majacy jako input nieuporzadkowana liste jest O(n²) ze wzgledu na uzycie count() w petli. count() samo w sobie jest O(n) i wykonujac sie z kazda iteracja petli podnosi zlozonosc do kwadratu. Ja sam dopiero sie ucze dlatego za wszelka cene probowalem zastosowac divide and conquer do optymalizacji na posortowanej liscie, ale nie wiem nawet czy to w tym przypadku mozliwe.
komentarz 2 grudnia 2017 przez Schizohatter Nałogowiec (39,600 p.)
Według mnie - "na logikę" - niemożliwe jest zejście poniżej O(n) przy takim zbiorze danych i takich informacjach jakie posiadamy. Siłą rzeczy musimy sprawdzić każdy element przecież.
komentarz 2 grudnia 2017 przez nastrand Nowicjusz (150 p.)
No wlasnie nie jestem pewien. Na liscie nieuporzadkowanej rzeczywiscie trzeba sprawdzic kazdy jeden element. Na liscie posortowanej wystarczy sprawdzic pierwszy element z danego rodzaju, zeby wiedziec ile ich jest, nie pojawia sie juz wiecej na liscie np. na koncu. Przy malych listach tego nie widac, ale zalozmy, ze na liscie jest 100 zer, 150 jedynek i jedna 9 na koncu. count() przeleci przez cala liste liczac zera, ale wiedzac po pierwszym wywolaniu, ze zer jest 100 mozna by je usunac z listy, oszczedzajac 99 kolejnych wywolan count. Mowiac krotko, zredukowac liczbe elementow na liscie po kazdym wywolaniu count(). Na tym sie wlasnie zacialem, bo zaczalem brnac w jeszcze bardziej zlozone rozwiazania zamiast prostsze.
komentarz 2 grudnia 2017 przez Schizohatter Nałogowiec (39,600 p.)
Ah, chciałeś zredukować swoje rozwiązanie. No to oczywiście. Myślałem, że chcesz jeszcze bardziej zredukować moje.

Gdybym miał to robić na liście nieuporządkowanej, to bym zebrał do osobnej tablicy informacje o tym, ile jest wystąpień każdej liczby (tablica asocjacyjna), a następnie przeleciał tylko tę tablicę, żeby znaleźć minimum. Nie wiem ile by to było (jedna pętla na zebranie danych i jedna na ich analizę).
komentarz 5 grudnia 2017 przez nastrand Nowicjusz (150 p.)
Najwiekszym problemem tego zadania sa jego ograniczenia. Najlatwiej byloby uzyc Counter() z biblioteki Pythona. Druga opcja to slowniki, ktore tez sa zabronione. Tak jak w Twoim przykladzie z tablicami, wystarczylaby jedna iteracja przypisujaca frekwencje do liczby na zasadzie key:value, a nastepnie wyciagniecie najmniejszej value uzywajac np. min(). Jak dostane formalne rozwiazanie tego zadania, to na pewno sie nim tutaj podziele.

Podobne pytania

0 głosów
1 odpowiedź 395 wizyt
pytanie zadane 14 lutego 2018 w C i C++ przez Kurczak Użytkownik (940 p.)
0 głosów
0 odpowiedzi 424 wizyt
pytanie zadane 12 stycznia 2018 w C i C++ przez marcin_kub Obywatel (1,420 p.)
+1 głos
1 odpowiedź 412 wizyt

93,182 zapytań

142,196 odpowiedzi

322,002 komentarzy

62,513 pasjonatów

Advent of Code 2024

Top 15 użytkowników

  1. 2127p. - dia-Chann
  2. 2092p. - Łukasz Piwowar
  3. 2079p. - Łukasz Eckert
  4. 2037p. - Tomasz Bielak
  5. 2006p. - rucin93
  6. 2005p. - Łukasz Siedlecki
  7. 1964p. - CC PL
  8. 1835p. - Adrian Wieprzkowicz
  9. 1785p. - Michal Drewniak
  10. 1744p. - rafalszastok
  11. 1684p. - Mikbac
  12. 1624p. - Anonim 3619784
  13. 1520p. - Marcin Putra
  14. 1480p. - ssynowiec
  15. 1365p. - Dawid128
Szczegóły i pełne wyniki

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj

Wprowadzenie do ITsec, tom 1 Wprowadzenie do ITsec, tom 2

Można już zamawiać dwa tomy książek o ITsec pt. "Wprowadzenie do bezpieczeństwa IT" - mamy dla Was kod: pasja (użyjcie go w koszyku), dzięki któremu uzyskamy aż 15% zniżki! Dziękujemy ekipie Sekuraka za fajny rabat dla naszej Społeczności!

...