Znajdowanie powtarzających się utworów na liście odtwarzania: rozwiązywanie problemu z kodowaniem w JavaScript

Playlist

Wykrywanie cyklicznych list odtwarzania w JavaScript

Znalezienie cykli lub powtórzeń jest częstym problemem podczas odpowiadania na pytania podczas rozmowy kwalifikacyjnej dotyczącej kodowania, szczególnie tych wymagających struktur danych, takich jak listy połączone. Ten problem pojawia się zwykle w przypadku list odtwarzania, w których utwory mogą łączyć się ze sobą w łańcuchu odniesień. Mówi się, że playlista jest powtarzalna, jeśli utwór nawiązuje do poprzedniego utworu.

Celem tego ćwiczenia z kodowania JavaScript jest napisanie funkcji określającej, czy jakiekolwiek utwory na liście odtwarzania się powtarzają. Przegląda każdy utwór jeden po drugim i sprawdza, czy istnieje odniesienie do poprzedniego utworu. Nawet doświadczeni programiści mogą natknąć się na subtelności odniesień do obiektów i kontroli pętli, próbując rozwiązać ten pozornie prosty problem w JavaScript.

Często problem wynika ze sposobu wyrażania logiki iteracji, szczególnie ze sposobu obsługi odniesień między obiektami. W tym przypadku rozwiązanie zależy od Twojej zdolności zrozumienia, w jaki sposób JavaScript zarządza odniesieniami do obiektów wewnątrz pętli. Podczas sprawdzania rozwiązania skoncentrujemy się na tym, jak odpowiednio ponownie przypisać i śledzić te odniesienia na liście odtwarzania.

Przeanalizujemy szczegółowo ten problem, przyjrzymy się niedociągnięciom istniejącego rozwiązania i w poniższej dyskusji zaproponujemy wykonalne rozwiązanie tej powtarzającej się przeszkody związanej z playlistami. Dzięki tej poprawce funkcja będzie w stanie dokładnie rozpoznać cykliczne odniesienia na liście odtwarzania i uzyskać zamierzony rezultat.

Rozkaz Przykład użycia
Set() Obiekt JavaScript Set() służy do przechowywania unikalnych danych. Aby pomóc w identyfikacji cykli playlisty, w tym przykładzie wykorzystano ją do śledzenia przeglądanych utworów, upewniając się, że żaden utwór nie zostanie odtworzony ponownie.
has() Obiekt Set() posiada funkcję has(). Sprawdza, czy w zbiorze istnieje określony element. Tutaj sprawdza, czy utwór został już usłyszany, wskazując, że lista odtwarzania się powtarza.
add() Obiekt Set() posiada funkcję has(). Sprawdza, czy dany element istnieje w zbiorze. Tutaj sprawdza, czy utwór został już usłyszany, wskazując, że lista odtwarzania się powtarza.
two-pointer technique Ta metoda, czasami nazywana algorytmem wykrywania cykli Floyda-Warshalla, porusza się po liście odtwarzania za pomocą dwóch wskaźników: wolnego i szybkiego. Aby skutecznie wykrywać pętle, powolny wskaźnik przesuwa się o jeden krok, a szybki wskaźnik o dwa kroki.
nextSong Klasa Song ma unikalną właściwość o nazwie nextSong, która odwołuje się do utworu znajdującego się po niej na liście odtwarzania. Umożliwia imitację struktury połączonej listy, w której każdy utwór odnosi się sekwencyjnie do każdego innego utworu.
describe() Funkcja opisu() platformy testowej Mocha służy do organizowania powiązanych testów jednostkowych. Dzieli testy na logiczne kategorie, takie jak playlisty, które się powtarzają, i te, które się nie powtarzają.
it() W Mocha definicja przypadku testowego nazywa się it(). Wskazuje konkretny przypadek, który należy przetestować, np. upewniając się, że funkcja odpowiednio rozpoznaje powtarzającą się playlistę.
assert.strictEqual() Ta metoda pochodzi z modułu Assert w Node.js. W tym przypadku weryfikuje przewidywany wynik funkcji powtarzania listy odtwarzania, sprawdzając, czy dwie wartości są ściśle równe.

Zrozumienie wykrywania cykli playlist w JavaScript

Pierwszy oferowany skrypt wykorzystuje metodę listy połączonej w celu identyfikacji utworów powtarzanych na liście odtwarzania, traktując każdy utwór jako węzeł. Struktura klas JavaScriptu służy do konstruowania pliku obiekt imitujący przepływ listy odtwarzania od utworu do utworu, przechowując nazwę utworu i odniesienie do następnego utworu. Głównym składnikiem rozwiązania jest śledzenie wcześniej napotkanej muzyki za pomocą pliku . Używamy pętli while do iteracji po utworach, sprawdzając, czy bieżący utwór był już słyszany. Jeśli tak, wskazujemy, że lista odtwarzania się powtarza, zwracając wartość true.

Algorytm wykrywania cykli Floyda, powszechnie nazywany techniką dwóch wskaźników, wykorzystuje się w drugim sposobie. Dzięki tej metodzie dwa wskaźniki poruszają się po liście odtwarzania z różną szybkością: jeden pomija dwa utwory i przesuwa się do przodu o jeden utwór na raz. Wskaźniki te ostatecznie się spotkają, jeśli nastąpi cykl, wskazując, że lista odtwarzania się powtarza. Ponieważ nie wymaga zapisywania oglądanych utworów, metoda ta zajmuje mniej miejsca i dlatego jest lepszą opcją w przypadku większych list odtwarzania.

Rozwiązania te pokazują również, jak tworzyć listy połączone w JavaScript, ponieważ linki własnościowe każdy sprzeciwiać się innemu. Wykrywanie cykli w pierwszym skrypcie wykorzystuje strukturę zestawu. Ponieważ zestawy zapewniają niepowtarzalność, po dodaniu do zestawu możemy błyskawicznie określić, czy utwór był już odtwarzany. To sprawia, że ​​zestawy są szczególnie przydatne. Pomaga nam to rozpoznać początek cyklu i zapobiega wpadnięciu w nieskończoną pętlę.

Wreszcie testy jednostkowe dołączone do obu strategii gwarantują, że rozwiązanie jest dokładne w różnych ustawieniach. Aby sprawdzić nasz kod, wykorzystaliśmy framework testowy Mocha. Node.js moduł służy do potwierdzenia, że ​​wyniki są zgodne z oczekiwaniami, a Mocha I Funkcje służą do logicznej struktury testów. Testy jednostkowe odgrywają kluczową rolę w procesie rozwoju, ponieważ sprawdzają, czy funkcja działa zgodnie z oczekiwaniami zarówno w przypadku powtarzających się, jak i jednorazowych list odtwarzania, zapewniając odporność rozwiązania.

Wykrywanie powtarzających się utworów na liście odtwarzania za pomocą JavaScript

Programowanie obiektowe w JavaScript z użyciem pętli while

class Song {
  constructor(name) {
    this.name = name;
    this.nextSong = null;
  }
  /
   * @return {boolean} true if the playlist is repeating, false if not.
   */
  isRepeatingPlaylist() {
    let seenSongs = new Set();
    let current = this;
    while (current) {
      if (seenSongs.has(current)) {
        return true; // Playlist is repeating
      }
      seenSongs.add(current);
      current = current.nextSong;
    }
    return false; // Playlist is not repeating
  }
}
// Testing the solution
let first = new Song("Hello");
let second = new Song("Eye of the Tiger");
let third = new Song("Third");
first.nextSong = second;
second.nextSong = third;
third.nextSong = first; // Creates a loop
console.log(first.isRepeatingPlaylist()); // true

Podejście alternatywne: użycie dwóch wskaźników do wykrywania cykli

Wykrywanie cykli listy połączonej za pomocą algorytmu Floyda-Warshalla

class Song {
  constructor(name) {
    this.name = name;
    this.nextSong = null;
  }
  /
   * @return {boolean} true if the playlist is repeating, false if not.
   */
  isRepeatingPlaylist() {
    let slow = this;
    let fast = this;
    while (fast !== null && fast.nextSong !== null) {
      slow = slow.nextSong; // move slow pointer by 1 step
      fast = fast.nextSong.nextSong; // move fast pointer by 2 steps
      if (slow === fast) {
        return true; // Loop detected
      }
    }
    return false; // No loop
  }
}
// Testing the solution
let first = new Song("Hello");
let second = new Song("Eye of the Tiger");
let third = new Song("Third");
first.nextSong = second;
second.nextSong = third;
third.nextSong = first; // Creates a loop
console.log(first.isRepeatingPlaylist()); // true

Testowanie jednostkowe pod kątem wykrywania pętli listy odtwarzania

Testowanie funkcji isRepeatingPlaylist za pomocą Node.js i Mocha

const assert = require('assert');
describe('isRepeatingPlaylist', function () {
  it('should return true for a repeating playlist', function () {
    let first = new Song('Song A');
    let second = new Song('Song B');
    let third = new Song('Song C');
    first.nextSong = second;
    second.nextSong = third;
    third.nextSong = first; // Creates a loop
    assert.strictEqual(first.isRepeatingPlaylist(), true);
  });
  it('should return false for a non-repeating playlist', function () {
    let first = new Song('Song A');
    let second = new Song('Song B');
    let third = new Song('Song C');
    first.nextSong = second;
    second.nextSong = third;
    assert.strictEqual(first.isRepeatingPlaylist(), false);
  });
});

Zaawansowane techniki wykrywania pętli w listach odtwarzania w JavaScript

Zrozumienie podstawowej struktury listy odtwarzania pod względem to interesująca część wykrywania pętli listy odtwarzania. Każdy utwór na niepowtarzającej się liście odtwarzania łączy się z utworem poprzedzającym, dopóki nie będzie już żadnych odniesień do tego utworu i lista się zakończy. Cykl inicjujemy, gdy utwór nawiązuje do poprzedniego, dlatego w pewnym sensie lista jest „nieskończona”. Znalezienie tego rodzaju cykli jest ważne nie tylko w przypadku list odtwarzania, ale także dla alokacji pamięci i algorytmów routingu.

Cykle te można skutecznie wykryć w JavaScript, wykorzystując techniki i struktury wskaźników, takie jak . Ponieważ zapewnia to niepowtarzalność i zapobiega ponownemu przeglądaniu utworów bez rozpoczynania cyklu, plik Ustawić jest szczególnie pomocny. Z drugiej strony podejście dwuwskaźnikowe Floyda-Warshalla jest rozwiązaniem zoptymalizowanym pod kątem przestrzeni, w którym dwa ruchome odniesienia, czyli wskaźniki, mają różne prędkości. Jeśli się połączą, zostanie znaleziony wzór.

Zwiększając wydajność tych algorytmów, możliwe jest szybkie przeglądanie list odtwarzania zawierających tysiące utworów. Technika dwóch wskaźników jest idealna w sytuacjach, gdy problemem jest wykorzystanie pamięci, ponieważ ma złożoność czasową O(n) i złożoność przestrzenną O(1). Ponadto sprawdzamy, czy nasze rozwiązania działają prawidłowo, stosując testy jednostkowe, takie jak te wykonane przy użyciu Mocha, które wykrywają zapętlone i niezapętlone listy odtwarzania w różnych ustawieniach.

  1. Co to jest cykl na liście odtwarzania?
  2. Kiedy utwór na liście odtwarzania nawiązuje do poprzedniego utworu, tworzona jest zapętlona sekwencja zwana cyklem.
  3. W jaki sposób technika dwóch wskaźników wykrywa cykl?
  4. Szybki wskaźnik przesuwa się o dwa kroki, a wolny wskaźnik przesuwa się o jeden krok na raz, korzystając z techniki dwóch wskaźników. Jeśli się zejdą, powstaje pętla.
  5. Dlaczego jest używany do wykrywania cykli?
  6. w , przechowywane są różne wartości. Pomocne jest zapisywanie słuchanej muzyki. Jeśli muzyka zostanie odtworzona ponownie, zostanie wykryta pętla.
  7. Czy mogę używać tego algorytmu do innych zastosowań?
  8. Rzeczywiście, dużo pracy zajmuje identyfikowanie pętli na połączonych listach, zarządzanie pamięcią i routing sieciowy przy użyciu techniki wykrywania cykli.
  9. Dlaczego używamy pętle w przeglądaniu playlist?
  10. Możemy iteracyjnie przeglądać listę odtwarzania za pomocą pętli, aż znajdziemy cykl lub dotrzemy do końca listy.

Identyfikacja cykli na liście odtwarzania może być trudna, szczególnie podczas nawigacji po zarządzaniu odniesieniami do obiektów w JavaScript. Możemy jednak skutecznie uporać się z tym problemem i usprawnić nasz kod, stosując techniki takie jak zastosowanie techniki dwóch wskaźników lub śledzenie odniesień do utworów za pomocą zestawu.

Znajomość zasad działania tych technik pomoże Ci skuteczniej rozwiązywać problemy, niezależnie od tego, czy zajmujesz się tym podczas rozmowy kwalifikacyjnej dotyczącej kodowania, czy w celach praktycznych. Używanie skutecznych struktur, takich jak i zrozumienie, w jaki sposób wskaźniki pomagają w wykrywaniu cykli, to główne wnioski, których należy się nauczyć.

  1. Inspirację dla algorytmów wykrywania cykli playlist zaczerpnięto z typowych problemów i technik związanych z listami połączonymi, takich jak algorytm Floyda-Warshalla. Dowiedz się więcej o listach połączonych i wykrywaniu cykli w tym obszernym źródle: Wykrywanie cykli w Wikipedii .
  2. Kolejnym świetnym zasobem jest dokumentacja JavaScript dla obiektów Set, które odgrywają kluczową rolę w pierwszym podejściu do rozwiązania: JavaScript ustawiony na MDN .
  3. Jeśli chodzi o bardziej szczegółowe techniki testowania w JavaScript, oficjalna dokumentacja Mocha była kluczowym źródłem zrozumienia struktury testów i asercji: Ramy testowania Mocha .
  4. Zapoznaj się z tym przewodnikiem na temat techniki dwóch wskaźników, która jest często używana w przypadku problemów z wykrywaniem cykli i jest jedną z zastosowanych tutaj skutecznych metod: Wykryj pętlę na liście połączonej .