日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

LeetCode 287. Find the Duplicate Number (时间复杂度O(n)) + 链表判断环

發(fā)布時間:2024/4/19 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 LeetCode 287. Find the Duplicate Number (时间复杂度O(n)) + 链表判断环 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

LeetCode 287. Find the Duplicate Number

暴力解法

時間 O(nlog(n)),空間O(n),按題目中Note“只用O(1)的空間”,照理是過不了的,但是可能判題并沒有卡空間復(fù)雜度,所以也能AC。

class Solution:# 基本思路為,將第一次出現(xiàn)的數(shù)字def findDuplicate(self, nums: List[int]) -> int:s = set()for i in nums:a = i in sif a == True:return ielse:s.add(i)

雙指針判斷環(huán)

時間O(n),空間O(1),思路十分巧妙,但是使用條件比較苛刻。根據(jù)題目給出的條件,恰好能用這種解法,這應(yīng)該也是出題人推薦的解法。

題意分析:

  • 輸入的序列有n+1個數(shù)字,每個數(shù)字在1~n之間取,這為構(gòu)成數(shù)字環(huán)創(chuàng)造了條件。
  • 只有一個數(shù)字有重復(fù),所以只可能構(gòu)成一個環(huán)。
  • 注:上面所說的環(huán)是指1->2->3->1

    以樣例1為例:[1,3,4,2,2]

    01234
    13422

    如下圖所示,其中2->4->2構(gòu)成環(huán),入環(huán)點為2

    解題思路

    由題意分析可知,每個樣例都可以畫成這樣一張圖,我們只需要找出圖中的環(huán),并找出入環(huán)點,即為所求的重復(fù)數(shù)字key,下面都用key表示所求的重復(fù)數(shù)字。

    為什么必定存在環(huán)

    以樣例1為例,圖中出現(xiàn)了5個點0-4,圖中存在5根指針線,5個點5根線,必定存在環(huán)。
    n個點,點的范圍去0~n-1,n根線,必定存在環(huán)。(n-1根線是恰好無環(huán)的情況,自己畫圖可知)

    找環(huán)的方法

    設(shè)置一個慢指針slow,一個快指針fast。slow每次走一步,fast每次走兩步,如果slow與fast能相遇,說明圖中存在環(huán),并且相遇點一定存在于環(huán)中。

    為什么key一定為入環(huán)點?

    有題意分析中的表可知,key的入度一定大于1,即不止一個點可以直接到key。而key一定存在于環(huán)中,所以key一定為入環(huán)點。樣例1中3,4都可到達(dá)2,2的入度2,2為入環(huán)點,即為所求的key。

    怎么找入環(huán)點key?

    slow和fast相交的點記為相遇點P。
    slow和fast從起點0到相遇點P運行步驟如下:

    這個相遇點P與起點0到達(dá)入環(huán)點key的步數(shù) 差距為環(huán)L的整數(shù)倍,故設(shè)置slow2從起點0開始,每次走一步,slow從相遇點P開始,每次走一步,slow和slow2一定會相遇在入環(huán)點key。

    我們可以有一個小小的證明,如下圖

    設(shè)起點0到達(dá)入環(huán)點key的步數(shù)為x,相遇點P到達(dá)入環(huán)點key的步數(shù)為y。
    設(shè)slow指針走到相遇點P的步數(shù)為t,fast走到相遇點P的步數(shù)為2*t。
    設(shè)走完環(huán)一圈的步數(shù)為L

    2 * t - x + y = M * L(一)
    t - x + y = N * L (二)
    fast指針在環(huán)中走的步數(shù)2t-x,此時到達(dá)相遇點P,key->P->key步數(shù)為2t-x+y = M * L,正好為L的M倍,M為常數(shù)。(一)式
    slow指針在環(huán)中走的步數(shù)t-x,此時到達(dá)相遇點P,key->P->key步數(shù)為t-x+y = N * L,正好為L的N倍,N為常數(shù)。(二)式

    2倍(二)式 減 (一)式
    y-x = (2N-M) * L
    所以y與x的步數(shù)差距為L倍的環(huán)。
    得證。

    如何確定起點0一定會進(jìn)入包含key的環(huán)?

    假設(shè)存在不包含key的環(huán),起點0在不包含key的環(huán)中繞圈。

    0a1a2a3a4a5a6
    b1b2b3b4b5b6b7

    按題意不包含環(huán),b[i]與b[j]一定不相等(i != j)
    由于b1~b7從1開始,所以b[i]只能從a[j]中取(1<=i<=7,1<=j<=6)
    從6個數(shù)字的集合a中取7個數(shù)字,所以假設(shè)不成立,必定存在相同數(shù)字b[k],即為key。

    代碼如下

    class Solution:def findDuplicate(self, nums: List[int]) -> int:# 如果只有兩個元素,第一個元素一定是重復(fù)元素if len(nums) == 2:return nums[0]# fast每次走兩步,slow每次走一步,起始點可以為任意位置fast = 0slow = 0# python沒有do while,所以在循環(huán)外寫了一遍slow = nums[slow]fast = nums[nums[fast]]while slow != fast:slow = nums[slow]fast = nums[nums[fast]]# fast從起點每次走一步,一定會與slow相遇,此時slow可能在環(huán)中走了多倍的L步。# L為環(huán)一圈的步數(shù)fast = 0while fast != slow:slow = nums[slow]fast = nums[fast]return fast

    總結(jié)

    以上是生活随笔為你收集整理的LeetCode 287. Find the Duplicate Number (时间复杂度O(n)) + 链表判断环的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。