Longest Palindrome
Otrzymujesz ciąg znaków s złożony z wielkich i małych liter. Ułóż jego litery tak, aby utworzyć jak najdłuższy palindrom, i zwróć jego długość. Możesz ułożyć litery w dowolnej kolejności i pominąć niektóre z nich, ale każdej litery możesz użyć najwyżej tyle razy, ile występuje w s.
Wielkie i małe litery są różnymi literami, więc Aa nie jest palindromem.
Funkcja
- sstring
- litery, których możesz używać, wielkie i małe
- Zwracainteger
- długość najdłuższego palindromu, jaki możesz ułożyć z tych liter
Ograniczenia
1 ≤ s.length ≤ 5 × 104szawiera tylko angielskie litery:a–zorazA–Z.- Nie musisz używać każdej litery.
Przykłady
- Wejście
- s = "coddyCode"
- Wyjście
- 5
- Wyjaśnienie
owystępuje dwa razy, adtrzy razy, pozostałe litery po razie. Para litero, para literdi jedna pozostała litera w środku dają długość 5, na przykładdoCod.
- Wejście
- s = "Aa"
- Wyjście
- 1
- Wyjaśnienie
Aiato różne litery, więc taka para nie istnieje. Pojedyncza litera sama w sobie jest palindromem o długości 1.
- Wejście
- s = "xxxyyy"
- Wyjście
- 5
- Wyjaśnienie
- Dwie litery
xi dwie literyytworzą pary, a jedna pozostała litera trafia na środek, jak wxyxyx. Ostatnia literaynie ma pary i pozostaje poza nimi.
Pytanie dodatkowe
Czy możesz zwrócić jeden z najdłuższych palindromów wraz z jego długością, nadal w czasie O(n)?
Podpowiedzi
Otwieraj je po kolei. Każda zdradza trochę więcej.
Palindrom czyta się tak samo od obu stron. Dopasuj jego pierwszą literę do ostatniej, drugą do przedostatniej i tak dalej. Co to mówi o liczbie wystąpień każdej litery?
Każda litera poza tą, która może znajdować się dokładnie na środku, występuje w dopasowanej parze. Zatem kolejność
snie ma żadnego znaczenia; liczy się tylko to, ile razy występuje każda litera.Policz każdą literę. Każdy wynik liczenia dostarcza największą parzystą część w postaci par, więc dodaj liczbę zaokrągloną w dół do najbliższej liczby parzystej. Jeśli którykolwiek wynik jest nieparzysty, jedna pozostała litera może znaleźć się na środku: dodaj 1, tylko raz.
Rozwiązanie
Ponieważ możesz przestawiać litery, kolejność s nie ma znaczenia, liczy się tylko to, ile razy występuje każda litera. W palindromie każda litera ma lustrzaną kopię po drugiej stronie, z wyjątkiem co najwyżej jednej litery na środku. Policz więc litery, zachowaj każdą parę i dodaj jedną literę na środek, jeśli jakaś litera zostanie.
Sortuj i łącz sąsiadów
Intuicja
Sortowanie umieszcza takie same litery obok siebie, więc każda para znajduje się obok siebie. W xxxyyy litery x na pozycjach 0 i 1 pasują do siebie: utwórz parę i przesuń się o dwie pozycje. Na indeksie 2 litery x i y różnią się, więc ta litera x pozostaje bez pary i przesuwasz się o jedną pozycję. Litery y na pozycjach 3 i 4 tworzą drugą parę, a ostatnia litera y pozostaje sama. Dwie pary dają 4, plus jedna środkowa litera: 5.
Litera pozostaje niewykorzystana dokładnie wtedy, gdy pary obejmują mniej niż wszystkie n litery, więc nie potrzebujesz osobnej flagi. Sortowanie zajmuje O(n log n) czasu, a posortowana kopia zajmuje O(n) pamięci.
Algorytm
- Posortuj litery w
s. - Przejdź przez posortowane litery, używając indeksu
i. Jeśli litery na pozycjachiii+1są takie same, dodaj 2 do długości i przesuń się o dwie pozycje; w przeciwnym razie przesuń się o jedną pozycję. - Jeśli długość jest mniejsza niż liczba liter, dodaj 1 za środkową literę.
- Zwróć długość.
def longestPalindrome(s):
letters = sorted(s)
n = len(letters)
length = 0
i = 0
while i + 1 < n:
if letters[i] == letters[i + 1]:
length += 2 # a pair: one copy on each side of the middle
i += 2
else:
i += 1
# A letter left without a partner can stand alone in the middle
if length < n:
length += 1
return lengthPolicz każdą literę
Intuicja
Zliczanie dostarcza tych samych informacji bez sortowania. Utrzymuj jeden licznik dla każdego kodu znaku — 128 liczników — dzięki czemu A i a trafią do różnych liczników. Litera występująca c razy dostarcza c zaokrąglone w dół do parzystej liczby liter.
Dla coddyCode pary liter o i d dają 4 litery. Zostaje pięć liter, z których dowolna może znaleźć się w środku: 5. Druga niesparowana litera nie miałaby swojego odbicia.
Jedno przejście po s wypełnia liczniki, a jedno przejście po 128 licznikach sumuje pary: czas O(n) i dodatkowa pamięć O(1) (O(n) w R, gdzie s jest najpierw konwertowane na wektor kodów).
Algorytm
- Utwórz 128 liczników ustawionych na 0 i dodaj 1 do licznika każdej litery z
s. - Dla każdego licznika dodaj do długości jego wartość zaokrągloną w dół do liczby parzystej.
- Jeśli długość jest mniejsza niż długość
s, któryś licznik jest nieparzysty, więc dodaj 1 za środkową literę. - Zwróć długość.
def longestPalindrome(s):
counts = [0] * 128 # one counter per character code, so 'A' and 'a' differ
for ch in s:
counts[ord(ch)] += 1
length = 0
for count in counts:
length += count // 2 * 2 # every pair fits, one copy on each side
# Fewer letters used than s has: some count is odd, so one letter can go in the middle
if length < len(s):
length += 1
return length
Pułapki i przypadki brzegowe
- Całkowite pomijanie nieparzystych liczności. Litera, która występuje 3 razy, nadal dostarcza jedną parę:
xxxyyydaje 5, a nie 1. - Dodawanie 1 za każdą nieparzystą liczność. Tylko jedna litera może znaleźć się w środku, więc
xxxyyydaje 5, a nie 6. - Traktowanie
Aiajako tej samej litery.Aanie zawiera żadnej pary, więc odpowiedź to 1, a nie 2. - Przydzielanie licznikom rozmiaru obejmującego tylko litery od
adoz. Wielkie litery mają kody od 65 do 90 i wypadają poza ten zakres; indeksuj według pełnego kodu znaku.
Najczęstsze pytania3
Czym różni się najdłuższy palindrom od najdłuższego podciągu palindromicznego?
Tutaj możesz przestawiać litery, więc liczą się tylko ich liczby i zliczanie rozwiązuje problem w czasie O(n). Problem Najdłuższego Palindromu w Podciągu wymaga znalezienia palindromu, który już występuje jako blok kolejnych liter, i wymaga innej metody, na przykład rozszerzania wokół każdego środka. Dla abab odpowiedzią w tym problemie jest 4 (abba), a w wersji dotyczącej podciągu — 3 (aba).
Jaka jest złożoność czasowa problemu najdłuższego palindromu?
Czas O(n) przy zliczaniu: każda litera dodaje 1 do jednego licznika, a sumowanie par wymaga odczytania 128 liczników niezależnie od długości s. Złożoność pamięciowa wynosi O(1). Sortowanie i łączenie sąsiednich elementów kosztuje O(n log n) czasu i O(n) pamięci.
Czy musisz użyć każdej litery z s?
Nie. Każda para zostaje wykorzystana, a na środku może znaleźć się najwyżej jedna niesparowana litera. Zatem odpowiedzią jest długość s, jeśli co najwyżej jedna litera występuje nieparzystą liczbę razy, a w przeciwnym razie długość s pomniejszona o liczbę liter występujących nieparzystą liczbę razy, plus 1.
Podobne zadania
Zadania oparte na tych samych pomysłach. Rozwiązanie dwóch lub trzech utrwala schemat.
def longestPalindrome(s):
# Napisz kod tutajTest #1
Test #2
Test #3
Argument
s = "coddyCode"
Oczekiwany wynik
5