-
Notifications
You must be signed in to change notification settings - Fork 43
/
find_the_duplicate_number.py
207 lines (172 loc) · 5.15 KB
/
find_the_duplicate_number.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
"""
287. Find the Duplicate Number
Medium
Given an array of integers nums containing n + 1 integers where each integer is in the range [1, n] inclusive.
There is only one repeated number in nums, return this repeated number.
You must solve the problem without modifying the array nums and uses only constant extra space.
Example 1:
Input: nums = [1,3,4,2,2]
Output: 2
Example 2:
Input: nums = [3,1,3,4,2]
Output: 3
Constraints:
1 <= n <= 105
nums.length == n + 1
1 <= nums[i] <= n
All the integers in nums appear only once except for precisely one integer which appears two or more times.
Follow up:
How can we prove that at least one duplicate number must exist in nums?
Can you solve the problem in linear runtime complexity?
"""
# V0
# IDEA : Counter
from collections import Counter
class Solution(object):
def findDuplicate(self, nums):
# edge case
if not nums:
return
cnt = Counter(nums)
for c in cnt:
if cnt[c] > 1:
return c
# V0
# IDEA : DICT
class Solution:
def findDuplicate(self, nums):
seen = dict()
for num in nums:
if num in seen:
return num
else:
if num not in seen:
seen[num] = 1
# V0'
# IDEA : SET
class Solution:
def findDuplicate(self, nums):
seen = set()
for num in nums:
if num in seen:
return num
seen.add(num)
# V1
# https://leetcode.com/articles/find-the-duplicate-number/
# IDEA : Sorting
class Solution:
def findDuplicate(self, nums):
nums.sort()
for i in range(1, len(nums)):
if nums[i] == nums[i-1]:
return nums[i]
# V1'
# https://leetcode.com/articles/find-the-duplicate-number/
# IDEA : SET
class Solution:
def findDuplicate(self, nums):
seen = set()
for num in nums:
if num in seen:
return num
seen.add(num)
# V1''
# https://leetcode.com/articles/find-the-duplicate-number/
# IDEA : Floyd's Tortoise and Hare (Cycle Detection)
# IDEA :
# -> TRANSFORM THE PROBLEM INTO "142 Linked List Cycle II"
# -> SO NOW the problem is to find the entrance of the cycle (cycle linked list)
class Solution:
def findDuplicate(self, nums):
# Find the intersection point of the two runners.
tortoise = hare = nums[0]
while True:
tortoise = nums[tortoise]
hare = nums[nums[hare]]
if tortoise == hare:
break
# Find the "entrance" to the cycle.
tortoise = nums[0]
while tortoise != hare:
tortoise = nums[tortoise]
hare = nums[hare]
return hare
# V1'''
# http://bookshadow.com/weblog/2015/09/28/leetcode-find-duplicate-number/
class Solution(object):
def findDuplicate(self, nums):
# The "tortoise and hare" step. We start at the end of the array and try
# to find an intersection point in the cycle.
slow = 0
fast = 0
# Keep advancing 'slow' by one step and 'fast' by two steps until they
# meet inside the loop.
while True:
slow = nums[slow]
fast = nums[nums[fast]]
if slow == fast:
break
# Start up another pointer from the end of the array and march it forward
# until it hits the pointer inside the array.
finder = 0
while True:
slow = nums[slow]
finder = nums[finder]
# If the two hit, the intersection index is the duplicate element.
if slow == finder:
return slow
# V1''''
# http://bookshadow.com/weblog/2015/09/28/leetcode-find-duplicate-number/
# IDEA : Binary Search)+ Pigeonhole Principle
class Solution(object):
def findDuplicate(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
low, high = 1, len(nums) - 1
while low <= high:
mid = (low + high) >> 1
cnt = sum(x <= mid for x in nums)
if cnt > mid:
high = mid - 1
else:
low = mid + 1
return low
# V1'''''
# https://www.hrwhisper.me/leetcode-find-the-duplicate-number/
# IDEA : BINARY SEARCH
class Solution(object):
def findDuplicate(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
L, R = 1, len(nums) - 1
while L <= R:
mid = (L + R) >> 1
cnt = sum([1 for num in nums if num <= mid])
if cnt <= mid:
L = mid + 1
else:
R = mid - 1
return L
# V1''''''
# https://www.hrwhisper.me/leetcode-find-the-duplicate-number/
# IDEA : TWO POINTERS
class Solution(object):
def findDuplicate(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
slow , fast = nums[0] , nums[nums[0]]
while slow != fast:
slow = nums[slow]
fast = nums[nums[fast]]
slow = 0
while slow != fast:
slow = nums[slow]
fast = nums[fast]
return slow
# V2