判斷迴文字符串、迴文鏈表、迴文數(python實現)

所謂迴文字符串,就是正讀和反讀都同樣的字符串,好比「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

判斷迴文鏈表

思路

  1. 咱們須要找到鏈表中點(快慢指針法)
  2. 將鏈表後半段倒置逆序排序
  3. 將前半段和後半段遍歷比較,判斷是否爲迴文鏈表,偶數狀況,使用偶數定位中點策略,要肯定是返回上中位數或下中位數

注意事項:指針

快慢指針定位中點時要區分奇偶狀況,奇數狀況,中點位置不須要矯正,偶數狀況,使用偶數定位中點策略,要肯定是返回上中位數或下中位數
若是是返回上中位數,後半部分串頭取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))
相關文章
相關標籤/搜索