Valid Palindrome
Du erhältst eine Zeichenfolge s. Behalte nur ihre Buchstaben und Ziffern bei, behandle Groß- und Kleinbuchstaben als denselben Buchstaben und entscheide, ob das Übriggebliebene von links nach rechts genauso gelesen wird wie von rechts nach links. Gib true zurück, wenn das der Fall ist, andernfalls false.
Alle anderen Zeichen, wie ., !, ?, :, ;, - oder _, werden ignoriert. Wenn s überhaupt keine Buchstaben oder Ziffern enthält, bleibt nichts übrig, und ein leerer Text gilt als Palindrom.
Funktion
- sstring
- der zu prüfende Text, einschließlich der Zeichensetzung
- Gibt zurückboolean
- wahr, wenn die Buchstaben und Ziffern von s in beide Richtungen gleich gelesen werden, wobei die Groß- und Kleinschreibung ignoriert wird
Einschränkungen
1 ≤ s.length ≤ 5 × 104senthält englische Buchstaben, Ziffern und die Satzzeichen. ! ? : ; - _, ohne Leerzeichen.
Beispiele
- Eingabe
- s = "Was_it_a_car_or_a_cat_I_saw?"
- Ausgabe
- true
- Erklärung
- Lässt man die Unterstriche und das Fragezeichen weg und schreibt die Großbuchstaben klein, erhält man
wasitacaroracatisaw, was rückwärts genauso aussieht.
- Eingabe
- s = "race-a-car"
- Ausgabe
- false
- Erklärung
- Ohne die Bindestriche lautet der Text
raceacar. Von rechts gelesen beginnt er mitracastatt mitrace: Dasein der Mitte hat einaals Spiegelpartner, daher lautet die Antwortfalse.
- Eingabe
- s = "Step-on-no-pets!"
- Ausgabe
- true
- Erklärung
- Der beibehaltene Text ist
steponnopets. Das großeSstimmt mit dem abschließendensüberein, da die Groß- und Kleinschreibung ignoriert wird, und die Bindestriche sowie das!spielen keine Rolle.
+25 versteckte Tests beim Einreichen
Weiterführende Frage
Kannst du das mit O(1) zusätzlichem Speicherplatz entscheiden, ohne eine bereinigte Kopie von s zu erstellen?
Tipps
Öffne sie nacheinander. Jeder verrät ein bisschen mehr.
Vergiss für einen Moment die Satzzeichen. Welche Zeichen von
svergleicht die Palindromprüfung tatsächlich, und in welchen Paaren?Der erste Buchstabe oder die erste Ziffer wird mit dem letzten verglichen, der zweite mit dem vorletzten und so weiter, jeweils in Kleinbuchstaben. Satzzeichen werden nie berücksichtigt und stehen daher nur beim Finden des nächsten Paars im Weg.
Gehe vom Anfang aus einen Index vorwärts und vom Ende aus einen rückwärts. Bewege jeden Index an allen Zeichen vorbei, die weder Buchstaben noch Ziffern sind, vergleiche die beiden Zeichen, wenn beide beibehalten werden, und höre auf, wenn sich die Indizes treffen.
Lösung
Die Palindromprüfung selbst ist die bekannte: Das erste beibehaltene Zeichen muss dem letzten entsprechen, das zweite dem vorletzten und so weiter. Knifflig an dieser Version ist, dass die verglichenen Zeichen nicht an gespiegelten Indizes von s stehen, weil Satzzeichen auf beiden Seiten ungleichmäßig verteilt sind. Du kannst sie zuerst entfernen oder zwei Zeiger beim Aufeinanderzugehen darüber hinwegsetzen lassen.
Bereinige die Zeichenkette und vergleiche sie dann mit ihrer Umkehrung
Idee
Erzeuge den Text, nach dem die Aufgabe tatsächlich fragt. Durchlaufe s, behalte jeden Buchstaben und jede Ziffer in Kleinbuchstaben bei und überspringe alles andere. Für Step-on-no-pets! ergibt das steponnopets. Jetzt stellt sich die ganz gewöhnliche Palindromfrage: Ist dieser Text gleich seiner Umkehrung?
Das ist korrekt, weil beim Bereinigen genau die Zeichen entfernt werden, die laut Aufgabenstellung ignoriert werden sollen, und die Groß- und Kleinschreibung vereinheitlicht wird, die ignoriert werden soll. Wenn s keine Buchstaben oder Ziffern enthält, ist der bereinigte Text leer. Ein leerer Text ist gleich seiner Umkehrung, also lautet die Antwort ohne Sonderfall true.
Jedes Zeichen wird einmal zum Bereinigen und ein weiteres Mal zum Vergleichen gelesen, daher beträgt die Laufzeit O(n). Die bereinigte Kopie und ihre Umkehrung benötigen zusätzlich O(n) Speicher, den der nächste Ansatz einspart.
Algorithmus
- Erstelle einen leeren Text
cleaned. - Füge für jedes Zeichen von
sdas Zeichen in Kleinbuchstaben hinzu, wenn es ein Buchstabe oder eine Ziffer ist. - Kehrt
cleanedum. - Gib zurück, ob
cleanedmit seiner Umkehrung übereinstimmt.
def isPalindrome(s):
cleaned = [ch.lower() for ch in s if ch.isalnum()]
return cleaned == cleaned[::-1]Zwei Zeiger, die Satzzeichen überspringen
Idee
Die bereinigte Kopie ist nur dazu da, damit du gespiegelte Zeichen vergleichen kannst. Du kannst denselben Vergleich auch direkt auf s durchführen. Setze left auf den ersten Index und right auf den letzten. Wenn bei einem Schritt left auf ein Satzzeichen zeigt, bewege ihn nach rechts; zeigt right auf ein Satzzeichen, bewege ihn nach links. Sobald beide auf Buchstaben oder Ziffern zeigen, vergleiche sie in Kleinbuchstaben. Bei einer Abweichung ist das Ergebnis false; stimmen sie überein, bewegen sich beide Zeiger nach innen.
Warum ist dies dieselbe Prüfung? Die Zeiger halten immer beim nächsten beibehaltenen Zeichen von jedem Ende an. Daher durchlaufen sie die Paare (erstes beibehaltenes, letztes beibehaltenes), (zweites beibehaltenes, vorletztes beibehaltenes) und so weiter – genau die Paare, die auch beim Vergleich mit der umgekehrten Zeichenfolge betrachtet werden. In Abc-dcbX ist das erste Paar A und X, und nach einem Vergleich lautet das Ergebnis false.
Bei jedem Schritt wird mindestens ein Zeiger bewegt, und sie halten an, wenn sie sich treffen, daher wird die Schleife höchstens n-mal ausgeführt. Außer den beiden Indizes wird nichts gespeichert, was einen zusätzlichen Speicherbedarf von O(1) ergibt.
Algorithmus
- Setze
left = 0undright = n-1. - Solange
left < rightgilt: Wenns[left]kein Buchstabe oder keine Ziffer ist, erhöheleftund fahre fort. - Andernfalls: Wenn
s[right]kein Buchstabe oder keine Ziffer ist, verringererightund fahre fort. - Vergleiche andernfalls die beiden Zeichen in Kleinbuchstaben. Wenn sie unterschiedlich sind, gib
falsezurück; wenn sie übereinstimmen, bewege beide Zeiger nach innen. - Wenn sich die Zeiger treffen, gib
truezurück.
def isPalindrome(s):
left, right = 0, len(s) - 1
while left < right:
if not s[left].isalnum():
left += 1
elif not s[right].isalnum():
right -= 1
elif s[left].lower() != s[right].lower():
return False
else:
left += 1
right -= 1
return True
Stolperfallen und Grenzfälle
Die meisten Fehler entstehen durch Zeichen, die übersprungen werden, und durch Groß- und Kleinschreibung.
s[i]mits[n-1-i]in der unveränderten Zeichenfolge vergleichen.a-baist ein Palindrom, sobald der Bindestrich entfernt wird, aber das Spiegelbild von-an Index 1 ist in der unveränderten Zeichenfolge dasban Index 2.- Beide Zeiger verschieben, obwohl nur einer davon auf einem Satzzeichen steht. Überspringe jeweils nur auf einer Seite, sonst geraten die beiden Seiten aus dem Takt.
- Satzzeichen in einer inneren Schleife überspringen, die über den anderen Zeiger hinausläuft. Bei
?!-_läuft eine unbeschränkte innere Schleife über das Ende der Zeichenfolge hinaus; prüfe bei jeder Bewegungleft < right. - Ziffern als unwichtig behandeln.
0Pistfalse: Die Ziffer0bleibt erhalten und wird verglichen; sie ist nicht der Buchstabep. falsezurückgeben, wenn nichts übrig bleibt. Eine Zeichenfolge, die nur aus Satzzeichen besteht, etwa., hat einen leeren bereinigten Text, der ein Palindrom ist.- Eine Zeichenfolge, die nur aus Ziffern besteht, etwa
12321, kann in PHP und R als Zahl interpretiert werden. Wandle sie zuerst in eine Zeichenfolge um.
Häufige Fragen4
Wie hoch ist die Zeitkomplexität von Valid Palindrome?
Beide Ansätze laufen in O(n)-Zeit, da jedes Zeichen eine konstante Anzahl von Malen betrachtet wird. Das vorherige Bereinigen benötigt für die Kopie zusätzlichen Speicherplatz von O(n). Die Version mit zwei Zeigern benötigt zusätzlichen Speicherplatz von O(1), da sie nur zwei Indizes speichert.
Wie prüfst du, ob etwas ein Palindrom ist, wenn du nicht alphanumerische Zeichen ignorierst?
Behalte an jedem Ende der Zeichenfolge einen Zeiger. Bewege einen Zeiger über jedes Zeichen hinweg, das kein Buchstabe und keine Ziffer ist. Wenn beide auf Buchstaben oder Ziffern zeigen, vergleiche sie in Kleinbuchstaben. Wenn jedes verglichene Paar übereinstimmt, bis sich die Zeiger treffen, ist die Zeichenfolge ein Palindrom.
Ist eine leere Zeichenfolge ein Palindrom?
Ein leerer Text ist in beiden Richtungen gleich, daher gibt eine Zeichenfolge wie ?!-_, deren Zeichen alle ignoriert werden, true zurück. Beide Ansätze erreichen dies ohne zusätzlichen Code: Der bereinigte Text entspricht seiner umgekehrten Version, und die beiden Zeiger finden nie ein Paar, das sich unterscheidet.
Warum zwei Zeiger verwenden, anstatt die Zeichenkette umzukehren?
Das Umkehren erfordert eine bereinigte Kopie und eine umgekehrte Kopie, was O(n) zusätzlichen Speicherplatz benötigt. Zwei Zeiger vergleichen dieselben Paare direkt und können beim ersten Unterschied anhalten, oft schon nach wenigen Schritten. Interviewer fragen als Folgefrage meist nach dieser Variante.
Ähnliche Aufgaben
Aufgaben mit denselben Ideen. Wer zwei oder drei davon löst, behält das Muster.
Python
def isPalindrome(s):
# Schreibe hier den CodeFall 1
Fall 2
Fall 3
Eingabe
s = "Was_it_a_car_or_a_cat_I_saw?"
Erwartet
true