所謂迴文字符串,就是正讀和反讀都同樣的字符串,好比「level」或者「noon」等等就是迴文串。便是對稱結構python
方法一:算法
def is_palindrome(s): return True if s == s[::-1] else False
方法二:測試
def is_palindrome(s): length = len(s) if not length: # 空字符串 return True mid_index = length // 2 # 若是s長度爲奇數則是中點,偶數則是後面那個中點 index = 0 status = True while index < mid_index: if s[index] == s[length - 1 - index]: index += 1 else: status = False break return status
注意事項:指針
快慢指針定位中點時要區分奇偶狀況,奇數狀況,中點位置不須要矯正,偶數狀況,使用偶數定位中點策略,要肯定是返回上中位數或下中位數
若是是返回上中位數,後半部分串頭取next,若是是返回下中位數,後半部分串頭既是當前節點位置,但前半部分串尾要刪除掉當前節點code
class Solution(object): def is_palindrome(self, head: ListNode) -> bool: if head is None: # 空 return False if head.next is None: # 1個節點 return True slow = fast = head # 1. 定中點 while fast and fast.next: slow = slow.next fast = fast.next.next # 快慢指針定位中點,此時fast已到達鏈尾,若是長度爲奇數,則slow到達中心點,長度爲偶數,則slow到達下中位點 # 2. 後半段倒置 pre = None # 倒置後的最後一個節點必爲None,以此肯定第三步遍歷時的終點 cur = slow # 當前要倒置的第一個節點 nxt = slow.next # 當前要倒置的節點的下一個節點 while nxt: # 只要沒有到達原鏈表的終點就一直進行倒置 cur.next = pre # 將當前節點的下一個節點指向"前"一個節點,進行倒置 # 相鄰節點倒置完成後,向後總體偏移1個單位 pre = cur cur = nxt nxt = cur.next # 當前cur是最後一個節點,須要和它前面的節點進行最後一次倒置,來完成整個後半段倒置 cur.next = pre # 3. cur就是倒置完成後的後半段的頭節點,同時遍歷cur和head,若是遍歷完cur未出現不一樣的節點,則爲迴文鏈表 while cur.next: if cur.val != head.val: return False cur = cur.next head = head.next # 此時cur爲後半段的最後一個節點,還須要判斷此時的cur和head的值是否相同 return cur.val == head.val
測試排序
# head =None head = ListNode(1) head.next = ListNode(2) head.next.next = ListNode(1) print(Solution().is_palindrome(head))
映入腦海的第一個想法是將數字轉換爲字符串,並檢查字符串是否爲迴文。可是,這須要額外的很是量空間來建立問題描述中所不容許的字符串。字符串
第二個想法是將數字自己反轉,而後將反轉後的數字與原始數字進行比較,若是它們是相同的,那麼這個數字就是迴文。 可是,若是反轉後的數字大於 int.MAX,咱們將遇到整數溢出問題。io
按照第二個想法,爲了不數字反轉可能致使的溢出問題,爲何不考慮只反轉int 數字的一半?畢竟,若是該數字是迴文,其後半部分反轉後應該與原始數字的前半部分相同。ast
例如,輸入 1221,咱們能夠將數字「1221」的後半部分從「21」反轉爲「12」,並將其與前半部分「12」進行比較,由於兩者相同,咱們得知數字 1221 是迴文。class
讓咱們看看如何將這個想法轉化爲一個算法。
首先,咱們應該處理一些臨界狀況。全部負數都不多是迴文,例如:-123 不是迴文,由於 - 不等於 3。因此咱們能夠對全部負數返回 false。
如今,讓咱們來考慮如何反轉後半部分的數字。 對於數字 1221,若是執行 1221 % 10,咱們將獲得最後一位數字 1,要獲得倒數第二位數字,咱們能夠先經過除以 10 把最後一位數字從 1221 中移除,1221 / 10 = 122,再求出上一步結果除以10的餘數,122 % 10 = 2,就能夠獲得倒數第二位數字。若是咱們把最後一位數字乘以10,再加上倒數第二位數字,1 * 10 + 2 = 12,就獲得了咱們想要的反轉後的數字。 若是繼續這個過程,咱們將獲得更多位數的反轉數字。
如今的問題是,咱們如何知道反轉數字的位數已經達到原始數字位數的一半?
咱們將原始數字除以 10,而後給反轉後的數字乘上 10,因此,當原始數字小於反轉後的數字時,就意味着咱們已經處理了一半位數的數字。
class Solution(object): def is_palindrome(self, num: int) -> bool: # 當 x < 0 時,x 不是迴文數 # 若是數字的最後一位是 0,爲了使該數字爲迴文,則其第一位數字也應該是 0 # 只有 0 知足這一屬性 if num < 0 or (num % 10 == 0 and num != 0): return False reverted_num = 0 while num > reverted_num: reverted_num = reverted_num * 10 + num % 10 num /= 10 # 當數字長度爲奇數時,咱們能夠經過 revertedNumber / 10 去除處於中位的數字。 # 例如,當輸入爲12321時,在 while 循環的末尾咱們能夠獲得 x = 12,revertedNumber = 123, # 因爲處於中位的數字不影響迴文(它老是與本身相等),因此咱們能夠簡單地將其去除。 return num == reverted_num or num == reverted_num / 10 # 測試 print(Solution().is_palindrome(0)) print(Solution().is_palindrome(10)) print(Solution().is_palindrome(101))