題目

給定一個包含 n + 1 個整數的數組 nums ,其數字都在 [1, n] 範圍內(包括 1 和 n),可知至少存在一個重複的整數。
假設 nums 只有 一個重複的整數 ,返回 這個重複的數 。
你設計的解決方案必須 不修改 數組 nums 且只用常量級 O(1) 的額外空間。

示例 1:

輸入:nums = [1,3,4,2,2]
輸出:2

示例 2:

輸入:nums = [3,1,3,4,2]
輸出:3

示例 3 :

輸入:nums = [3,3,3,3,3]
輸出:3

提示:

  • 1 <= n <= 105
  • nums.length == n + 1
  • 1 <= nums[i] <= n
  • nums 中 只有一個整數 出現 兩次或多次 ,其餘整數均只出現一次

題解

class Solution:
    def findDuplicate(self, nums: List[int]) -> int:
        # 將尋找數組重複數的問題,轉換成環形鏈表尋找入環節點的問題
        # 使用快慢指針的方法實現
        slow = nums[0]
        fast = nums[0]
        # 數組中的元素可以視為指向數組中其他位置的“指針”
        while True:
        	# 起初的疑惑是slow和fast作為索引對應的數值是隨機的,那麼得到的slow和fast是跳躍的。
        	# 但是你仔細舉個例子畫一畫你會發現,fast就是比slow多走一個“節點”位置,fast走過的slow都會走過
            slow = nums[slow] # 這個相當於慢指針走一步
            fast = nums[nums[fast]] # 這個相當於快指針走兩步
            if slow==fast:
                break
        # 相遇之後,將快指針置為數組起點
        fast = nums[0]
        # 每次走一步,當兩個指針再次相遇時,就是入環的節點
        while slow != fast:
            slow = nums[slow]
            fast = nums[fast]
        return fast

快慢指針的解法,如果存在重複值,那麼鏈表中一定存在環,相遇之後,將快指針置為數組起點,再次相遇就是重複點的位置。