數據結構與算法 —— 鏈表linked list(06)

迴文鏈表

 連接html

請檢查一個鏈表是否爲迴文鏈表。python

進階:
你能在 O(n) 的時間和 O(1) 的額外空間中作到嗎?算法

 

解題思路:

迴文鏈表的特色就是對稱。微信

把鏈表放到棧中去,利用棧的先進後出的規則,和原鏈表一一作比較。所有相等,則是迴文鏈表。數據結構

代碼實現以下:app

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def isPalindrome(self, head):
        """
        :type head: ListNode
        :rtype: bool
        請注意:python3中的list是有pop的方法的
        """
        stack = []
        cur = head
        while cur:
            stack.append(cur)
            cur = cur.next
        while stack:
            if stack.pop().val != head.val:
                return False
            else:
                head=head.next
        return True
View Code

時間(O(N)),空間(O(N)),顯然不符合。ide

進階:

將鏈表的後半部分翻轉過來,從兩頭開始一一判斷,若是都相等,則爲迴文鏈表。這個的時間是O(N),空間是O(1):post

代碼以下:學習

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None
def reveseList(head):
    cur = head
    pre = None
    while cur:
        cur_next = cur.next
        cur.next = pre
        pre = cur
        cur=cur_next
    return pre


class Solution:
    def isPalindrome(self, head):
        """
        :type head: ListNode
        :rtype: bool
        請注意:python3中的list是有pop的方法的
        """
        if not head:
            return True
        fast = slow =head
        while fast.next and fast.next.next:
            fast = fast.next.next
            slow = slow.next
        slow = slow.next
        slow = reveseList(slow)
        while slow:
            if slow.val != head.val:
                return False
            slow = slow.next
            head = head.next
        return True
    
View Code

環形鏈表

 連接spa

給定一個鏈表,返回鏈表開始入環的第一個節點。 若是鏈表無環,則返回 null

說明:不容許修改給定的鏈表。

進階:
你是否能夠不用額外空間解決此題?

解題思路:

涉及到環形的數據結構,均可以考慮Floyd算圈問題(又叫龜兔賽跑問題)。

算法描述

(1)求環

初始狀態下,假設已知某個起點爲節點爲節點S。現設兩個指針t和h,將它們均指向S。

同時讓t和h往前推動,h的速度爲t的2倍),直到h沒法前進,即到達某個沒有後記的節點時,就能夠肯定從S出發不會遇到環。反之當t與h再次相遇時,就能夠肯定從S出發必定會進入某個環,設其爲環C。(h和t推動的步數差是環長的倍數)

(2)求環的長度

上述算法剛判斷出存在環C時,t和h位於同一節點,設其爲節點M。僅需令h不動,而t不斷推動,最終又會返回節點M,統計這一次t推動的步數,就是環C的長度。

(3)求環的起點

爲了求出環C的起點,只要令h仍均位於節點M,而令t返回起點節點S。隨後,同時讓t和h往前推動,且速度相同。持續該過程直至t與h再一次相遇,此相遇點就是環C的一個起點。

 

假設出發起點到環起點的距離爲m,已經肯定有環,環的周長爲n,(第一次)相遇點距離環的起點的距離是k。那麼當二者相遇時,慢指針(t)移動的總距離i = m + a * n + k,快指針(h)的移動距離爲2i,2i = m + b * n + k。其中,a和b分別爲t和h在第一次相遇時轉過的圈數。讓二者相減(快減慢),那麼有i = (b - a) * n。即i是圈長度的倍數。

將一個指針移到出發起點S,另外一個指針仍呆在相遇節點M處二者同時移動,每次移動一步。當第一個指針前進了m,即到達環起點時,另外一個指針距離鏈表起點爲i + m。考慮到i爲圈長度的倍數,能夠理解爲指針從鏈表起點出發,走到環起點,而後繞環轉了幾圈,因此第二個指針也必然在環的起點。即二者相遇點就是環的起點。

 

具體的代碼實現:

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution(object):
    def detectCycle(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        pre = high = low = head
        if not high or not high.next:
            return None
        while high  and high.next:
            high = high.next.next
            low = low.next
            if high == low:
                break
        if high != None and high == low:
            while high != head:
                high = high.next
                head = head.next
            return high

        return None  
View Code

 

參考:https://blog.csdn.net/u012482487/article/details/49798169

 

最近的收穫:

在作這些題的時間,有時候感受拿着筆在本上畫畫,寫寫,真的比憑空想象要不少,畫一畫你的思路,作一下推演,能讓你更加的理解。

絕知此事要躬行,說的就是這個意思。但願能和你們一塊兒多交流,咱們互相學習。

 

coding交流羣:226704167,願和各位一塊兒進步!

微信公衆號:

相關文章
相關標籤/搜索