Leetcode 287 尋找重複數

2021-10-06 12:19:35 字數 2329 閱讀 9206

給定乙個包含 n + 1 個整數的陣列 nums,其數字都在 1 到 n 之間(包括 1 和 n),可知至少存在乙個重複的整數。假設只有乙個重複的整數,找出這個重複的數。

說明:

不能更改原陣列(假設陣列是唯讀的)。

只能使用額外的 o(1) 的空間。

時間複雜度小於 o(n

2)

o(n^2)

o(n2) 。

陣列中只有乙個重複的數字,但它可能不止重複出現一次。

題目本身不難,暴力解遍歷, 使用map索引,o(n

)o(n)

o(n)

空間,o(n

)o(n)

o(n)

時間。或者用陣列自身做索引,o(1

)o(1)

o(1)

空間,o(n

)o(n)

o(n)

時間。

func

findduplicate

(nums [

]int

)int

t = nums[

(nums[0]

)]nums[

(nums[0]

)]= nums[0]

nums[0]

= t }

return nums[0]

}

但是,本題要求不能改變原陣列,而且要o(1

)o(1)

o(1)

空間。不能再用索引的方式了。

換乙個思路。將陣列作為鍊錶來考慮。

對於陣列a[]

aa[

],將其看作鍊錶的記錄, i

−>a[

i]

i -> a[i]

i−>a[

i]。即 a[i

]=

ja[i] = j

a[i]=j

,表示 i

−>

ji -> j

i−>j。

如果,陣列中存在相同的值,那麼說明鍊錶有兩個節點指向相同的節點,即鍊錶中有環。

這樣就變成了在鍊錶中找環的問題了,相同的節點即是環的入口。

以下抄錄leetcode

假設環長為 l

ll,從起點到環的入口的步數是 a

aa,從環的入口繼續走 b

bb 步到達相遇位置,從相遇位置繼續走 c

cc 步回到環的入口,則有 b+c

=l

b+c=l

b+c=

l,其中 l

ll、a

aa、b

bb、c

cc 都是正整數。根據上述定義,慢指標走了 a+b

a+ba+

b 步,快指標走了 2(a

+b

)2(a+b)

2(a+b)

步。從另乙個角度考慮,在相遇位置,快指標比慢指標多走了若干圈,因此快指標走的步數還可以表示成 a+b

+k

la+b+kl

a+b+kl

,其中 k

kk 表示快指標在環上走的圈數。聯立等式,可以得到

2 (a

+b)=

a+b+

kl

2(a+b)=a+b+kl

2(a+b)

=a+b

+kl解得 a=k

l−

ba=kl-b

a=kl−b

,整理可得

a =(

k−1)

l+(l

−b)=

(k−1

)l+c

a=(k-1)l+(l-b)=(k-1)l+c

a=(k−1

)l+(

l−b)

=(k−

1)l+

c從上述等式可知,如果慢指標從起點出發,快指標從相遇位置出發,每次兩個指標都移動一步,則慢指標走了 a

aa 步之後到達環的入口,快指標在環裡走了 k−1

k-1k−

1 圈之後又走了 c

cc 步,由於從相遇位置繼續走 c

cc 步即可回到環的入口,因此快指標也到達環的入口。兩個指標在環的入口相遇,相遇點就是答案。

func

findduplicate

(nums [

]int

)int

slow =

0for slow != fast

return slow

}

LeetCode 287 尋找重複數

參考 給定乙個包含 n 1 個整數的陣列 nums,其數字都在 1 到 n 之間 包括 1 和 n 可知至少存在乙個重複的整數。假設只有乙個重複的整數,找出這個重複的數。示例 1 輸入 1,3,4,2,2 輸出 2示例 2 輸入 3,1,3,4,2 輸出 3說明 不能更改原陣列 假設陣列是唯讀的 只...

LeetCode 287(尋找重複數)

給定乙個包含 n 1 個整數的陣列 nums,其數字都在 1 到 n 之間 包括 1 和 n 可知至少存在乙個重複的整數。假設只有乙個重複的整數,找出這個重複的數。示例 1 輸入 1,3,4,2,2 輸出 2示例 2 輸入 3,1,3,4,2 輸出 3說明 不能更改原陣列 假設陣列是唯讀的 只能使用...

leetcode287 尋找重複數

1.二分查詢 參考 可以認為有兩個陣列,乙個是原陣列,乙個是1 n的範圍陣列 無重複 每次對low high的範圍陣列做二分,取中間數mid,然後去原陣列中統計小於等於mid的數目,如果大於mid 如果無重複,那麼應該小於等於mid 說明重複的那個數字在1 mid之間,結合範圍即在 low mid之...