Palindrome String
Ciąg znaków jest palindromem, gdy czyta się go tak samo od lewej do prawej, jak od prawej do lewej, na przykład level. Napisz funkcję, która otrzymuje ciąg znaków s składający się z małych liter alfabetu angielskiego i zwraca true, jeśli s jest palindromem, a w przeciwnym razie false.
Funkcja
- sstring
- łańcuch znaków zapisany małymi literami do sprawdzenia
- Zwracaboolean
- true, gdy s czyta się tak samo w obu kierunkach
Ograniczenia
1 ≤ s.length ≤ 5 × 104szawiera wyłącznie małe litery alfabetu angielskiego (a–z).
Przykłady
- Wejście
- s = "racecar"
- Wyjście
- true
- Wyjaśnienie
- Porównuj od zewnątrz do środka:
rzr,aza,czc. Środkoweenie ma pary i jej nie potrzebuje, więc odpowiedź totrue.
- Wejście
- s = "abba"
- Wyjście
- true
- Wyjaśnienie
- Przy parzystej długości każda litera ma swoją parę: dwa
apasują do siebie, a dwabpasują do siebie, więc odpowiedzią jesttrue.
- Wejście
- s = "coddy"
- Wyjście
- false
- Wyjaśnienie
- Pierwsza litera
ci ostatnia literayjuż się różnią, więccoddynie jest palindromem, a odpowiedź tofalse.
+16 ukrytych testów przy wysłaniu
Pytanie dodatkowe
Zdanie takie jak Was it a car or a cat I saw jest palindromem, jeśli zignorujesz wielkość liter, spacje i znaki interpunkcyjne. Jak zmieniłbyś dwa wskaźniki, aby pomijały te znaki?
Podpowiedzi
Otwieraj je po kolei. Każda zdradza trochę więcej.
Jeśli
sjest palindromem, któremu znakowi musi być równy jego pierwszy znak?Znak o indeksie
imusi być równy znakowi o indeksien-1-i. Każdą taką parę wystarczy sprawdzić tylko raz, więc wystarczy sprawdzić połowę indeksów.Umieść jeden indeks na początku, a drugi na końcu. Porównaj oba znaki, zwróć
falsew przypadku niezgodności i przesuwaj oba indeksy o jeden krok do środka, aż się spotkają.
Rozwiązanie
Palindrom jest równy swojemu odwróceniu, więc bezpośrednie sprawdzenie polega na utworzeniu odwróconego ciągu i porównaniu ich. Lepsze sprawdzenie nie tworzy niczego: pierwszy znak musi pasować do ostatniego, drugi do przedostatniego i tak dalej, w kierunku środka. Dwa indeksy przesuwające się do środka sprawdzają te pary w miejscu i zatrzymują się przy pierwszej niezgodności.
Porównaj ciąg znaków z jego odwróceniem
Intuicja
Odczytywanie s tak samo w obu kierunkach oznacza, że s jest równe swojemu odwróceniu. Odwróć je więc i porównaj: racecar po odwróceniu to racecar, a coddy po odwróceniu to yddoc, co jest inne.
Tworzenie odwróconego ciągu i porównywanie ich sprawia, że każdy znak jest odwiedzany raz, więc złożoność czasowa wynosi O(n). Odwrócona kopia zawiera dodatkowe n znaków, co oznacza O(n) dodatkowej pamięci: przy n = 5 × 10^4 to 50 000 znaków utworzonych tylko po to, by je porównać i odrzucić.
Ta metoda wykonuje też całą pracę za każdym razem. O tym, że coddy nie jest palindromem, decydują jego pierwsza i ostatnia litera, a mimo to ta metoda odwraca wszystkie pięć liter, zanim je porówna.
Algorytm
- Zbuduj odwróconą wersję
s, używając funkcji odwracającej dostępnej w danym języku lub pętli przechodzącej od ostatniego znaku do pierwszego. - Porównaj odwróconą wersję z
s. - Zwróć
true, jeśli są równe, a w przeciwnym raziefalse.
def isPalindrome(s):
return s == s[::-1]Dwa wskaźniki z obu końców
Intuicja
Odwrócenie przenosi znak z indeksu i na indeks n-1-i, więc s jest równe swojemu odwróceniu dokładnie wtedy, gdy s[i] jest równe s[n-1-i] dla każdego i. Każda para pojawia się na tej liście dwa razy, więc sprawdzaj tylko lewą połowę. Ustaw left na indeksie 0, a right na indeksie n-1, porównaj oba znaki i przesuń oba wskaźniki o jeden krok do środka.
Zatrzymaj się, gdy wskaźniki się spotkają lub miną. W racecar sprawdzają pary indeksów (0, 6), (1, 5) i (2, 4), a następnie spotykają się na indeksie 3, gdzie znajduje się środkowe e, które nie potrzebuje pary. W abba sprawdzają (0, 3) i (1, 2), a potem mijają się. Pierwsza różniąca się para dowodzi, że odpowiedź to false, więc od razu zwracasz wynik: dla coddy rozstrzygnięcie następuje po jednym porównaniu.
Wykonuje się najwyżej n / 2 porównań, co oznacza czas O(n), a jedyną używaną pamięcią są dwa indeksy, czyli O(1) miejsca. Wyjątkiem jest R: najpierw odczytuje ciąg jako wektor kodów znaków, co kosztuje O(n).
Algorytm
- Ustaw
left = 0iright = n-1. - Dopóki
left < right, porównujs[left]zs[right]. - Jeśli się różnią, zwróć
false. - W przeciwnym razie dodaj 1 do
left, odejmij 1 odrighti powtórz. - Gdy wskaźniki się spotkają lub miną, każda para będzie dopasowana: zwróć
true.
def isPalindrome(s):
left, right = 0, len(s) - 1
while left < right:
if s[left] != s[right]:
return False
left += 1
right -= 1
return True
Pułapki i przypadki brzegowe
Pętla jest krótka, więc błędy dotyczą jej granic i instrukcji zwracających wynik.
- Zwracanie
trueod razu po dopasowaniu jednej pary.abcaprzechodzi test dla zewnętrznej pary, ale nie dla wewnętrznej, więctruemożna zwrócić dopiero po zakończeniu pętli. - Ustawienie
rightnanzamiastn-1, co powoduje odczyt poza końcem (w C — terminującego'\0'). W Lua i R indeksy biegną od1don, więc tamrightzaczyna odn. - Porównywanie ciągów znaków na podstawie adresu. W C
reversed == sporównuje dwa wskaźniki i dla świeżej kopii zawsze zwraca fałsz; użyjstrcmp. - Budowanie odwróconego ciągu za pomocą
result = result + chw pętli. Każdy krok kopiuje dotychczasowy ciąg, co oznacza około1.25 × 10^9kopiowań znaków dla 50,000 liter. - Indeksowanie ciągu znaków w Swift za pomocą liczby całkowitej. Taki kod się nie kompiluje; przejdź po
s.utf8za pomocą jego własnych indeksów albo skopiuj znaki do tablicy.
Najczęstsze pytania4
Jak sprawdzić, czy ciąg znaków jest palindromem?
Porównaj pierwszy znak z ostatnim, drugi z przedostatnim i tak dalej, przesuwając się ku środkowi. Jeśli jakakolwiek para się różni, ciąg nie jest palindromem; jeśli wszystkie pary są zgodne, jest nim. Dwa indeksy, które zaczynają na obu końcach i przesuwają się do środka, wykonują to w jednym przebiegu.
Czy potrafisz sprawdzić, czy słowo jest palindromem, bez użycia dodatkowej pamięci?
Tak. Sprawdzanie za pomocą dwóch wskaźników odczytuje znaki w miejscu i przechowuje tylko dwa indeksy, więc wykorzystuje dodatkową przestrzeń O(1). Porównanie s z jego odwróconą wersją jest krótsze do zapisania, ale tworzy drugi ciąg znaków o długości n.
Jaka jest złożoność czasowa sprawdzania, czy ciąg znaków jest palindromem?
To O(n) dla ciągu znaków o długości n. Sprawdzenie za pomocą dwóch wskaźników wykonuje co najwyżej n / 2 porównań i zatrzymuje się przy pierwszej niezgodności, więc o ciągu znaków, którego pierwszy i ostatni znak są różne, można rozstrzygnąć po jednym porównaniu.
Czy pojedynczy znak jest palindromem?
Tak. Jeden znak czyta się tak samo w obu kierunkach, więc odpowiedź to true. W pętli z dwoma wskaźnikami left i right oba zaczynają od indeksu 0, pętla nigdy się nie uruchamia, a funkcja zwraca true.
Podobne zadania
Zadania oparte na tych samych pomysłach. Rozwiązanie dwóch lub trzech utrwala schemat.
Python
def isPalindrome(s):
# Wpisz kod tutajPrzypadek 1
Przypadek 2
Przypadek 3
Wejście
s = "racecar"
Oczekiwane
true