Kim jest idol w zbiorze?

Specyfikacja problemu:

Dane:

  • n – liczba naturalna; liczba osób

  • znajomosci – tablica o wymiarach n × n; przechowuje liczby naturalne 0 oraz 1; tablica informacji na temat tego, które osoby się znają

Wynik:

  • komunikat wskazujący lidera zbioru lub informujący, że zbiór nie ma idola

Na przyjęciu znajduje się n osób. Osoby oznaczone są numerami od 0 do n1. Ponieważ jest to duża impreza, nie wszyscy goście się znają. Osoba A może znać osobę B, co niekoniecznie musi oznaczać, że osoba B zna osobę A. Może się okazać, że na przyjęciu pojawiła się osoba na tyle popularna, że jest znana przez wszystkich. Jeżeli ponadto okaże się, że osoba ta nie zna nikogo spośród pozostałych gości, możemy nazwać ją idolem.

Poniżej zaprezentowano dwuwymiarową tablicę typu logicznego, która określa stan znajomości wśród osób znajdujących się na przyjęciu. Jeżeli wartość znajomość[A][B] wynosi 1 (zauważmy, że to tablica liczb całkowitych, nie tablica boolowska), to przyjmujemy, że osoba A zna osobę B. Dla porządku przyjmujemy, że dana osoba nie zna siebie samej.

Linia 1. n ← 5. Linia 2. znajomość otwórz nawias kwadratowy n zamknij nawias kwadratowy otwórz nawias kwadratowy n zamknij nawias kwadratowy ← otwórz nawias kwadratowy. Linia 3. otwórz nawias kwadratowy 0 przecinek 1 przecinek 0 przecinek 1 przecinek 1 zamknij nawias kwadratowy przecinek. Linia 4. otwórz nawias kwadratowy 0 przecinek 0 przecinek 1 przecinek 0 przecinek 1 zamknij nawias kwadratowy przecinek. Linia 5. otwórz nawias kwadratowy 0 przecinek 1 przecinek 0 przecinek 1 przecinek 1 zamknij nawias kwadratowy przecinek. Linia 6. otwórz nawias kwadratowy 1 przecinek 1 przecinek 1 przecinek 0 przecinek 1 zamknij nawias kwadratowy przecinek. Linia 7. otwórz nawias kwadratowy 0 przecinek 0 przecinek 0 przecinek 0 przecinek 0 zamknij nawias kwadratowy. Linia 8. zamknij nawias kwadratowy.
Polecenie 1

Czy na podstawie powyższej tablicy jesteś w stanie wskazać, która osoba jest idolem?

Zastanówmy się, ile pytań „Czy osoba A zna osobę B?” musimy zadać, aby sprawdzić, czy na przyjęciu pojawił się idol oraz kto nim jest.

Spróbujmy dokładnie przeanalizować informację, która wynika z odpowiedzi na pojedyncze pytanie: „Czy osoba A zna osobę B?” w kontekście wyszukiwania idola. Ponieważ idol jest osobą, która musi być znana przez każdego oraz sama nie może znać nikogo, wymienione wyżej pytanie pozwala nam stwierdzić, która z osób A lub B na pewno nie jest idolem. Jeżeli odpowiedź na nie brzmi twierdząco, wiemy, że osoba A nie może być idolem, ponieważ zna przynajmniej jedną osobę. Jeśli odpowiedź jest przecząca, to z kolei osoba B nie może być uznana za idola, ponieważ istnieje przynajmniej jedna osoba, która jej nie zna.

Tym sposobem możemy wyznaczyć idealnego kandydata na idola, zadając tylko 0 do n1 pytań. Zapiszmy ten proces w postaci pseudokodu:

Linia 1. n ← 5. Linia 2. znajomość otwórz nawias kwadratowy n zamknij nawias kwadratowy otwórz nawias kwadratowy n zamknij nawias kwadratowy ← otwórz nawias kwadratowy. Linia 3. otwórz nawias kwadratowy 0 przecinek 1 przecinek 0 przecinek 1 przecinek 1 zamknij nawias kwadratowy przecinek. Linia 4. otwórz nawias kwadratowy 0 przecinek 0 przecinek 1 przecinek 0 przecinek 1 zamknij nawias kwadratowy przecinek. Linia 5. otwórz nawias kwadratowy 0 przecinek 1 przecinek 0 przecinek 1 przecinek 1 zamknij nawias kwadratowy przecinek. Linia 6. otwórz nawias kwadratowy 1 przecinek 1 przecinek 1 przecinek 0 przecinek 1 zamknij nawias kwadratowy przecinek. Linia 7. otwórz nawias kwadratowy 0 przecinek 0 przecinek 0 przecinek 0 przecinek 0 zamknij nawias kwadratowy. Linia 8. zamknij nawias kwadratowy. Linia 9. kandydat ← 0. Linia 11. dla i znak równości 1 przecinek 2 przecinek kropka kropka kropka przecinek n minus 1 wykonuj. Linia 12. jeżeli znajomość otwórz nawias kwadratowy kandydat zamknij nawias kwadratowy otwórz nawias kwadratowy i zamknij nawias kwadratowy to. Linia 13. kandydat znak równości i.

Następnie sprawdzimy, czy wyznaczony kandydat może być idolem. W tym celu musimy przepytać wszystkich gości, czy znają wyznaczonego kandydata, a także przepytać kandydata, czy nie zna nikogo. Każdy z tych procesów będzie składał się z zadania n1 pytań.

Do wcześniejszego pseudokodu dopiszemy linijki odpowiadające za sprawdzenie, czy wyznaczony kandydat jest idolem:

Linia 1. n ← 5. Linia 2. znajomość otwórz nawias kwadratowy n zamknij nawias kwadratowy otwórz nawias kwadratowy n zamknij nawias kwadratowy ← otwórz nawias kwadratowy. Linia 3. otwórz nawias kwadratowy 0 przecinek 1 przecinek 0 przecinek 1 przecinek 1 zamknij nawias kwadratowy przecinek. Linia 4. otwórz nawias kwadratowy 0 przecinek 0 przecinek 1 przecinek 0 przecinek 1 zamknij nawias kwadratowy przecinek. Linia 5. otwórz nawias kwadratowy 0 przecinek 1 przecinek 0 przecinek 1 przecinek 1 zamknij nawias kwadratowy przecinek. Linia 6. otwórz nawias kwadratowy 1 przecinek 1 przecinek 1 przecinek 0 przecinek 1 zamknij nawias kwadratowy przecinek. Linia 7. otwórz nawias kwadratowy 0 przecinek 0 przecinek 0 przecinek 0 przecinek 0 zamknij nawias kwadratowy. Linia 8. zamknij nawias kwadratowy. Linia 10. kandydat ← 0. Linia 12. dla i znak równości 1 przecinek 2 przecinek kropka kropka kropka przecinek n minus 1 wykonuj. Linia 13. jeżeli znajomość otwórz nawias kwadratowy kandydat zamknij nawias kwadratowy otwórz nawias kwadratowy i zamknij nawias kwadratowy to. Linia 14. kandydat ← i. Linia 15. prawy ukośnik prawy ukośnik w przeciwnym wypadku kandydat dalej może być idolem. Linia 17. prawy ukośnik prawy ukośnik przepytaj gości przecinek czy znają kandydata. Linia 18. dla i znak równości 0 przecinek 1 przecinek kropka kropka kropka przecinek n minus 1 wykonuj. Linia 19. prawy ukośnik prawy ukośnik sprawdź czy osoba i nie jest kandydatem. Linia 20. jeżeli kandydat wykrzyknik znak równości i to. Linia 21. prawy ukośnik prawy ukośnik sprawdź przecinek czy osoba i zna kandydata. Linia 22. jeżeli wykrzyknik znajomość otwórz nawias kwadratowy i zamknij nawias kwadratowy otwórz nawias kwadratowy kandydat zamknij nawias kwadratowy to. Linia 23. prawy ukośnik prawy ukośnik osoba i nie zna kandydata. Linia 24. prawy ukośnik prawy ukośnik kandydat nie jest idolem. Linia 25. prawy ukośnik prawy ukośnik idol nie istnieje. Linia 26. wypisz cudzysłów Idol nie istnieje cudzysłów. Linia 27. zakończ działanie pętli. Linia 29. prawy ukośnik prawy ukośnik przepytaj kandydata przecinek czy nie zna gości. Linia 30. dla i znak równości 0 przecinek 1 przecinek kropka kropka kropka przecinek n minus 1 wykonuj. Linia 31. prawy ukośnik prawy ukośnik sprawdź przecinek czy kandydat nie jest osobą i. Linia 32. jeżeli kandydat wykrzyknik znak równości i to. Linia 33. prawy ukośnik prawy ukośnik sprawdź przecinek czy kandydat nie zna osoby i. Linia 34. jeżeli znajomość otwórz nawias kwadratowy kandydat zamknij nawias kwadratowy otwórz nawias kwadratowy i zamknij nawias kwadratowy to. Linia 35. prawy ukośnik prawy ukośnik kandydat zna osobę i. Linia 36. prawy ukośnik prawy ukośnik kandydat nie jest idolem. Linia 37. prawy ukośnik prawy ukośnik idol nie istnieje. Linia 38. wypisz cudzysłów Idol nie istnieje cudzysłów. Linia 39. zakończ wykonywanie programu. Linia 41. wypisz cudzysłów Idolem jest osoba numer cudzysłów plus kandydat.

Powyższy kod można skrócić, wykorzystując podobieństwo dwóch pętli:

Linia 1. n ← 5. Linia 2. znajomość otwórz nawias kwadratowy n zamknij nawias kwadratowy otwórz nawias kwadratowy n zamknij nawias kwadratowy ← otwórz nawias kwadratowy. Linia 3. otwórz nawias kwadratowy 0 przecinek 1 przecinek 0 przecinek 1 przecinek 1 zamknij nawias kwadratowy przecinek. Linia 4. otwórz nawias kwadratowy 0 przecinek 0 przecinek 1 przecinek 0 przecinek 1 zamknij nawias kwadratowy przecinek. Linia 5. otwórz nawias kwadratowy 0 przecinek 1 przecinek 0 przecinek 1 przecinek 1 zamknij nawias kwadratowy przecinek. Linia 6. otwórz nawias kwadratowy 1 przecinek 1 przecinek 1 przecinek 0 przecinek 1 zamknij nawias kwadratowy przecinek. Linia 7. otwórz nawias kwadratowy 0 przecinek 0 przecinek 0 przecinek 0 przecinek 0 zamknij nawias kwadratowy. Linia 8. zamknij nawias kwadratowy. Linia 10. kandydat ← 0. Linia 12. dla i znak równości 1 przecinek 2 przecinek kropka kropka kropka przecinek n minus 1 wykonuj. Linia 13. jeżeli znajomość otwórz nawias kwadratowy kandydat zamknij nawias kwadratowy otwórz nawias kwadratowy i zamknij nawias kwadratowy to. Linia 14. kandydat ← i. Linia 15. prawy ukośnik prawy ukośnik w przeciwnym wypadku kandydat dalej może być idolem. Linia 17. prawy ukośnik prawy ukośnik sprawdź przecinek czy kandydat jest idolem. Linia 18. dla i znak równości 0 przecinek 1 przecinek kropka kropka kropka przecinek n minus 1 wykonuj. Linia 19. prawy ukośnik prawy ukośnik sprawdź czy nie pytamy kandydata o samego siebie. Linia 20. prawy ukośnik prawy ukośnik oraz czy czy osoba i zna kandydata. Linia 21. prawy ukośnik prawy ukośnik oraz czy kandydat nie zna osoby i. Linia 22. jeżeli kandydat wykrzyknik znak równości i. Linia 23. oraz wykrzyknik znajomość otwórz nawias kwadratowy i zamknij nawias kwadratowy otwórz nawias kwadratowy kandydat zamknij nawias kwadratowy. Linia 24. oraz znajomość otwórz nawias kwadratowy kandydat zamknij nawias kwadratowy otwórz nawias kwadratowy i zamknij nawias kwadratowy to. Linia 25. prawy ukośnik prawy ukośnik osoba i nie zna kandydata. Linia 26. prawy ukośnik prawy ukośnik lub kandydat zna osobę i. Linia 27. prawy ukośnik prawy ukośnik kandydat nie jest idolem. Linia 28. prawy ukośnik prawy ukośnik idol nie istnieje. Linia 29. wypisz cudzysłów Idol nie istnieje cudzysłów. Linia 30. zakończ wykonywanie programu. Linia 32. wypisz cudzysłów Idolem jest osoba numer cudzysłów plus kandydat.

Przedstawiony algorytm pozwala nam na znalezienie idola po zadaniu 3n1 pytań.

By to uzasadnić, przypomnijmy jak działa omówiony algorytm. Najpierw sprawdzamy, czy każda kolejna osoba (poza pierwszą) zna obecnego kandydata (czyli pierwszą osobę). Daje to n1 pytań.

Następny krok wymaga sprawdzana, czy kolejne osoby z grupy znają kandydata (czyli znowu zadajemy n1 pytań) oraz czy kandydat zna te kolejne osoby (kolejne n1 pytań).

By znaleźć idola zadajemy 3n1 pytań. To oznacza, że złożoność czasowa omówionego algorytmu wynosi On.

Implementacja algorytmu

To, czy dana osoba zna inną, przedstawimy za pomocą tzw. macierzy sąsiedztwa. Będzie to dwuwymiarowa tablica wypełniona zerami, jeżeli relacja znajomości z drugą osobą nie zachodzi, oraz jedynkami, jeżeli ta relacja zaistniała. Każdy wiersz tej macierzy będzie oznaczał stan wiedzy jednej osoby, zaś każda kolumna będzie oznaczała wiedzę o konkretnej osobie. Uznajemy, że żadna osoba nie zna samej siebie, dlatego przekątna tej tablicy będzie wypełniona zerami.

Linia 1. macierz znak równości otwórz nawias kwadratowy. Linia 2. otwórz nawias kwadratowy 0 przecinek 1 przecinek 0 przecinek 1 przecinek 1 zamknij nawias kwadratowy przecinek. Linia 3. otwórz nawias kwadratowy 0 przecinek 0 przecinek 1 przecinek 0 przecinek 1 zamknij nawias kwadratowy przecinek. Linia 4. otwórz nawias kwadratowy 0 przecinek 1 przecinek 0 przecinek 1 przecinek 1 zamknij nawias kwadratowy przecinek. Linia 5. otwórz nawias kwadratowy 1 przecinek 1 przecinek 1 przecinek 0 przecinek 1 zamknij nawias kwadratowy przecinek. Linia 6. otwórz nawias kwadratowy 0 przecinek 0 przecinek 0 przecinek 0 przecinek 0 zamknij nawias kwadratowy. Linia 7. zamknij nawias kwadratowy.

Teraz zapiszemy pętlę, która przejdzie po wszystkich wierszach tej macierzy. W każdym jej wykonaniu będziemy sprawdzali, czy znaleźliśmy wiersz wypełniony samymi zerami – oznacza to, że mamy potencjalnego idola. Jeżeli okaże się, że dowolna inna osoba go nie zna, zbiór nie będzie miał innego idola.

Linia 1. macierz znak równości otwórz nawias kwadratowy. Linia 2. otwórz nawias kwadratowy 0 przecinek 1 przecinek 0 przecinek 1 przecinek 1 zamknij nawias kwadratowy przecinek. Linia 3. otwórz nawias kwadratowy 0 przecinek 0 przecinek 1 przecinek 0 przecinek 1 zamknij nawias kwadratowy przecinek. Linia 4. otwórz nawias kwadratowy 0 przecinek 1 przecinek 0 przecinek 1 przecinek 1 zamknij nawias kwadratowy przecinek. Linia 5. otwórz nawias kwadratowy 1 przecinek 1 przecinek 1 przecinek 0 przecinek 1 zamknij nawias kwadratowy przecinek. Linia 6. otwórz nawias kwadratowy 0 przecinek 0 przecinek 0 przecinek 0 przecinek 0 zamknij nawias kwadratowy. Linia 7. zamknij nawias kwadratowy. Linia 9. for i in range otwórz nawias okrągły len otwórz nawias okrągły macierz zamknij nawias okrągły zamknij nawias okrągły dwukropek. Linia 10. if macierz otwórz nawias kwadratowy i zamknij nawias kwadratowy znak równości znak równości otwórz nawias kwadratowy 0 zamknij nawias kwadratowy asterysk len otwórz nawias okrągły macierz zamknij nawias okrągły dwukropek.

Teraz stworzymy kolejną pętlę, która przejdzie po wszystkich elementach w kolumnie informującej nas o tym, czy osoba o indeksie i jest znana. Wyjątkiem będzie tutaj sam wiersz wypełniony zerami – zostanie on pominięty. Jeżeli znajdziemy tam jakiekolwiek zero, natychmiastowo stwierdzimy, że zbiór ten nie ma idola i zakończymy wykonywanie pętli.

Linia 1. macierz znak równości otwórz nawias kwadratowy. Linia 2. otwórz nawias kwadratowy 0 przecinek 1 przecinek 0 przecinek 1 przecinek 1 zamknij nawias kwadratowy przecinek. Linia 3. otwórz nawias kwadratowy 0 przecinek 0 przecinek 1 przecinek 0 przecinek 1 zamknij nawias kwadratowy przecinek. Linia 4. otwórz nawias kwadratowy 0 przecinek 1 przecinek 0 przecinek 1 przecinek 1 zamknij nawias kwadratowy przecinek. Linia 5. otwórz nawias kwadratowy 1 przecinek 1 przecinek 1 przecinek 0 przecinek 1 zamknij nawias kwadratowy przecinek. Linia 6. otwórz nawias kwadratowy 0 przecinek 0 przecinek 0 przecinek 0 przecinek 0 zamknij nawias kwadratowy. Linia 7. zamknij nawias kwadratowy. Linia 9. for i in range otwórz nawias okrągły len otwórz nawias okrągły macierz zamknij nawias okrągły zamknij nawias okrągły dwukropek. Linia 10. if macierz otwórz nawias kwadratowy i zamknij nawias kwadratowy znak równości znak równości otwórz nawias kwadratowy 0 zamknij nawias kwadratowy asterysk len otwórz nawias okrągły macierz zamknij nawias okrągły dwukropek. Linia 11. for x in macierz otwórz nawias kwadratowy dwukropek i zamknij nawias kwadratowy plus macierz otwórz nawias kwadratowy i plus 1 dwukropek zamknij nawias kwadratowy dwukropek. Linia 12. if x otwórz nawias kwadratowy i zamknij nawias kwadratowy znak równości znak równości 0 dwukropek. Linia 13. print otwórz nawias okrągły cudzysłów Zbior nie ma idola cudzysłów zamknij nawias okrągły. Linia 14. break.

Następnie, ponownie korzystając z konstrukcji for‑else, dodamy wyświetlanie informacji o znalezionym idolu. Jeżeli pętla przechodząca po wszystkich elementach w kolumnie wykona się bez wywołania instrukcji break, wtedy mamy pewność, że osoba o indeksie i jest idolem. Dodamy też instrukcję else na koniec pętli przechodzącej po wierszach – odpowiada to sytuacji, w której nie znaleźliśmy żadnej osoby nieznającej nikogo.

Linia 1. macierz znak równości otwórz nawias kwadratowy. Linia 2. otwórz nawias kwadratowy 0 przecinek 1 przecinek 0 przecinek 1 przecinek 1 zamknij nawias kwadratowy przecinek. Linia 3. otwórz nawias kwadratowy 0 przecinek 0 przecinek 1 przecinek 0 przecinek 1 zamknij nawias kwadratowy przecinek. Linia 4. otwórz nawias kwadratowy 0 przecinek 1 przecinek 0 przecinek 1 przecinek 1 zamknij nawias kwadratowy przecinek. Linia 5. otwórz nawias kwadratowy 1 przecinek 1 przecinek 1 przecinek 0 przecinek 1 zamknij nawias kwadratowy przecinek. Linia 6. otwórz nawias kwadratowy 0 przecinek 0 przecinek 0 przecinek 0 przecinek 0 zamknij nawias kwadratowy. Linia 7. zamknij nawias kwadratowy. Linia 9. for i in range otwórz nawias okrągły len otwórz nawias okrągły macierz zamknij nawias okrągły zamknij nawias okrągły dwukropek. Linia 10. if macierz otwórz nawias kwadratowy i zamknij nawias kwadratowy znak równości znak równości otwórz nawias kwadratowy 0 zamknij nawias kwadratowy asterysk len otwórz nawias okrągły macierz zamknij nawias okrągły dwukropek. Linia 11. for x in macierz otwórz nawias kwadratowy dwukropek i zamknij nawias kwadratowy plus macierz otwórz nawias kwadratowy i plus 1 dwukropek zamknij nawias kwadratowy dwukropek. Linia 12. if x otwórz nawias kwadratowy i zamknij nawias kwadratowy znak równości znak równości 0 dwukropek. Linia 13. print otwórz nawias okrągły cudzysłów Zbior nie ma idola cudzysłów zamknij nawias okrągły. Linia 14. break. Linia 15. else dwukropek. Linia 16. print otwórz nawias okrągły f cudzysłów Idol to otwórz nawias klamrowy i zamknij nawias klamrowy cudzysłów zamknij nawias okrągły. Linia 17. break. Linia 18. else dwukropek. Linia 19. print otwórz nawias okrągły cudzysłów Zbior nie ma idola cudzysłów zamknij nawias okrągły.

Po uruchomieniu tego programu otrzymamy informację, że idolem jest osoba o numerze 4.

Przykładowe macierze, dla których idol nie istnieje:

Linia 1. macierz znak równości otwórz nawias kwadratowy. Linia 2. otwórz nawias kwadratowy 0 przecinek 1 przecinek 0 przecinek 1 przecinek 1 zamknij nawias kwadratowy przecinek. Linia 3. otwórz nawias kwadratowy 0 przecinek 0 przecinek 1 przecinek 0 przecinek 1 zamknij nawias kwadratowy przecinek. Linia 4. otwórz nawias kwadratowy 0 przecinek 1 przecinek 0 przecinek 1 przecinek 1 zamknij nawias kwadratowy przecinek. Linia 5. otwórz nawias kwadratowy 1 przecinek 1 przecinek 1 przecinek 0 przecinek 0 zamknij nawias kwadratowy przecinek. Linia 6. otwórz nawias kwadratowy 0 przecinek 0 przecinek 0 przecinek 0 przecinek 0 zamknij nawias kwadratowy. Linia 7. zamknij nawias kwadratowy.
Linia 1. macierz znak równości otwórz nawias kwadratowy. Linia 2. otwórz nawias kwadratowy 0 przecinek 1 przecinek 0 przecinek 1 przecinek 1 zamknij nawias kwadratowy przecinek. Linia 3. otwórz nawias kwadratowy 0 przecinek 0 przecinek 1 przecinek 0 przecinek 1 zamknij nawias kwadratowy przecinek. Linia 4. otwórz nawias kwadratowy 0 przecinek 1 przecinek 0 przecinek 1 przecinek 1 zamknij nawias kwadratowy przecinek. Linia 5. otwórz nawias kwadratowy 1 przecinek 1 przecinek 1 przecinek 0 przecinek 0 zamknij nawias kwadratowy przecinek. Linia 6. otwórz nawias kwadratowy 0 przecinek 0 przecinek 0 przecinek 1 przecinek 0 zamknij nawias kwadratowy. Linia 7. zamknij nawias kwadratowy.

Słownik

macierz sąsiedztwa
macierz sąsiedztwa

w teorii grafów jest to tablica zer i jedynek, informująca o tym, czy istnieją ścieżki między odpowiednimi wierzchołkami grafu

zbiór uporządkowany
zbiór uporządkowany

zbiór, w którym wszystkie elementy są posortowane według pewnej ich cechy; w przypadku liczb najczęściej jest to ich wartość