leetcode 第141題 環形鏈表, 第142題 環形鏈表 II , 第287題 尋找重複數(Python解法)

leetcode 第141題 環形鏈表, 第142題 環形鏈表 II , 第287題 尋找重複數(Python解法)

今天的前兩題是關於環形鏈表的,第三題是要找出數組中出現的重複數字,乍一看和前兩題無關,但是最後也用到了環形鏈表的知識,只是這裏的着手點比較隱蔽。

問題分析

141題 環形鏈表

先看141題,141題是給出一個鏈表,然後判斷該鏈表是否是一個循環鏈表,如果是返回True,如果不是返回False。
這一題直接用快慢指針解題,首先快慢指針都指向頭節點,然後慢節點每次都向後移一個節點,而快指針每次向後移兩個節點。如果慢節點或慢節點的下個節點是否爲空,如果爲空,說明不是環形鏈表,返回False。如果不是,接着向下移動。
假如鏈表中存在環,由於快指針每次都比慢指針多走一倍的距離,所以最後快指針一定會將慢指針“套圈”相遇。
如第一張圖所示,開始快慢指針都指向頭節點,在移動後一段距離後,如第二張圖所示,快指針“套圈”慢指針,再次相遇。再次相遇說明鏈表存在環,所以返回True。
在這裏插入圖片描述

在這裏插入圖片描述

142題 環形鏈表 II

142題是141題的升級,它不僅先要判斷鏈表是否有環,還有找出環形鏈表的入口。
開始的處理和141題一樣,先用快慢指針找出第二次相遇的節點(如果不是環形鏈表就返回None,不需要向下繼續操作)。再次相遇後,如下圖所示:
要求返回的是節點4,現在是在節點7相遇。此外,在這個圖上做一點標識,節點1到節點4的距離a=3,節點4到節點7的距離爲b=3。相遇時,慢節點從節點1到節點7,總共移動的距離爲a+b=6,而快節點移動的距離是慢節點的兩倍,爲12(從1->4->7->4->7)。此外可以知道的是從節點7到節點4的距離也爲a=3。

在這裏插入圖片描述
有了這些準備,下面就好辦了。將其中的一個指針(這裏用快指針)重新移到頭節點1。這時候兩個指針都同時向後移動。每次移動一個位置。
在這裏插入圖片描述
到最後,兩個指針移動a的距離,重新在節點4相遇,此時只要返回節點4就OK了。
在這裏插入圖片描述

287題 尋找重複數

287題如下,在一個包含n+1個元素的數組中找出重複的元素,其中元素的值在1~n之間。關於數組所有元素的值小於其長度時,可以使用原位改動元素值的方法,但是第一個條件就說此數組不可更改,所以此方法不可用,排序等方法也不可用;而且第二個條件爲只能使用常數級空間,所以不能用集合存儲元素。第三個條件是時間複雜度小於O(n2),所以不能用暴力法來解題。
在這裏插入圖片描述
此題可以用上述的環形鏈表的思想巧妙的來解答。假設下面是一個待求的數組,裏面的重複元素爲9。
在這裏插入圖片描述
接下來將此數組看成是一個鏈表。根據數組的元素來構建鏈表,比如nums[0]=2,那麼節點2指向的下一個節點就是nums[2]=9, 節點9的下一個節點是nums[9]=1,由於題目限制,是永遠不會超過數組的範圍的。到了節點7時,它的下一個節點爲nums[7]=9,這樣就形成了一個環,而且環的入口(節點9)即爲重複元素。
得到的鏈表如下:
在這裏插入圖片描述
構造好環形鏈表之後,接下來就可以用142題的方法來解題了。用這種方法時間複雜度爲O(n),空間複雜度爲O(1),而且沒有改變數組元素的值。

源碼

141題 環形鏈表

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

class Solution(object):
    def hasCycle(self, head):
        """
        :type head: ListNode
        :rtype: bool
        """
        if head:
            slow = head
            fast = head
            while fast and fast.next:
                slow = slow.next
                fast = fast.next.next
                if fast == slow:
                    return True
        return False

142題 環形鏈表 II

class Solution(object):
    def detectCycle(self, head):
        """
        :type head: ListNod
        :rtype: ListNode
        """
        fast = slow = head
        while fast and fast.next:
            fast = fast.next.next
            slow = slow.next
            if fast == slow:
                fast = head
                while fast != slow:
                    fast = fast.next
                    slow = slow.next
                return fast
        return None

287題 尋找重複數

class Solution:
    def findDuplicate(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        slow = nums[nums[0]]
        fast = nums[nums[nums[0]]]
        while slow != fast:
            slow = nums[slow]
            fast = nums[nums[fast]]
        slow = nums[0]
        while slow != fast:
            slow = nums[slow]
            fast = nums[fast]
        return slow

在這裏插入圖片描述

謝謝

給大家拜個晚年

祝大家晚年幸福

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章