Skip to content

Commit 3923835

Browse files
committed
feat: add solutions to lc problem: No.0287
No.0287.Find the Duplicate Number
1 parent 7cef6ba commit 3923835

File tree

8 files changed

+131
-160
lines changed

8 files changed

+131
-160
lines changed

solution/0200-0299/0287.Find the Duplicate Number/README.md

Lines changed: 47 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,11 @@
5454

5555
**方法一:二分查找**
5656

57-
如果值范围在 `[1, mid]` 的数小于等于 mid,说明此范围内没有重复的数,否则说明有重复数。
57+
我们可以发现,如果 $[1,..x]$ 中的数字个数大于 $x$,那么重复的数字一定在 $[1,..x]$ 中,否则重复的数字一定在 $[x+1,..n]$ 中。
58+
59+
因此,我们可以二分枚举 $x$,每次判断 $[1,..x]$ 中的数字个数是否大于 $x$,从而确定重复的数字在哪个区间中,进而缩小区间范围,直到找到重复的数字。
60+
61+
时间复杂度 $O(n \times \log n)$,其中 $n$ 是数组 $nums$ 的长度。空间复杂度 $O(1)$。
5862

5963
<!-- tabs:start -->
6064

@@ -65,15 +69,10 @@
6569
```python
6670
class Solution:
6771
def findDuplicate(self, nums: List[int]) -> int:
68-
left, right = 1, len(nums) - 1
69-
while left < right:
70-
mid = (left + right) >> 1
71-
cnt = sum(v <= mid for v in nums)
72-
if cnt > mid:
73-
right = mid
74-
else:
75-
left = mid + 1
76-
return left
72+
def f(x: int) -> bool:
73+
return sum(v <= x for v in nums) > x
74+
75+
return bisect_left(range(len(nums)), True, key=f)
7776
```
7877

7978
### **Java**
@@ -83,22 +82,22 @@ class Solution:
8382
```java
8483
class Solution {
8584
public int findDuplicate(int[] nums) {
86-
int left = 1, right = nums.length - 1;
87-
while (left < right) {
88-
int mid = (left + right) >> 1;
85+
int l = 0, r = nums.length - 1;
86+
while (l < r) {
87+
int mid = (l + r) >> 1;
8988
int cnt = 0;
9089
for (int v : nums) {
9190
if (v <= mid) {
9291
++cnt;
9392
}
9493
}
9594
if (cnt > mid) {
96-
right = mid;
95+
r = mid;
9796
} else {
98-
left = mid + 1;
97+
l = mid + 1;
9998
}
10099
}
101-
return left;
100+
return l;
102101
}
103102
}
104103
```
@@ -109,19 +108,20 @@ class Solution {
109108
class Solution {
110109
public:
111110
int findDuplicate(vector<int>& nums) {
112-
int left = 1, right = nums.size() - 1;
113-
while (left < right) {
114-
int mid = (left + right) >> 1;
111+
int l = 0, r = nums.size() - 1;
112+
while (l < r) {
113+
int mid = (l + r) >> 1;
115114
int cnt = 0;
116-
for (int& v : nums)
117-
if (v <= mid)
118-
++cnt;
119-
if (cnt > mid)
120-
right = mid;
121-
else
122-
left = mid + 1;
115+
for (int& v : nums) {
116+
cnt += v <= mid;
117+
}
118+
if (cnt > mid) {
119+
r = mid;
120+
} else {
121+
l = mid + 1;
122+
}
123123
}
124-
return left;
124+
return l;
125125
}
126126
};
127127
```
@@ -130,22 +130,15 @@ public:
130130
131131
```go
132132
func findDuplicate(nums []int) int {
133-
left, right := 1, len(nums)-1
134-
for left < right {
135-
mid := (left + right) >> 1
133+
return sort.Search(len(nums), func(x int) bool {
136134
cnt := 0
137135
for _, v := range nums {
138-
if v <= mid {
136+
if v <= x {
139137
cnt++
140138
}
141139
}
142-
if cnt > mid {
143-
right = mid
144-
} else {
145-
left = mid + 1
146-
}
147-
}
148-
return left
140+
return cnt > x
141+
})
149142
}
150143
```
151144

@@ -157,47 +150,47 @@ func findDuplicate(nums []int) int {
157150
* @return {number}
158151
*/
159152
var findDuplicate = function (nums) {
160-
let left = 1,
161-
right = nums.length - 1;
162-
while (left < right) {
163-
const mid = (left + right) >> 1;
153+
let l = 0;
154+
let r = nums.length - 1;
155+
while (l < r) {
156+
const mid = (l + r) >> 1;
164157
let cnt = 0;
165-
for (let v of nums) {
158+
for (const v of nums) {
166159
if (v <= mid) {
167160
++cnt;
168161
}
169162
}
170163
if (cnt > mid) {
171-
right = mid;
164+
r = mid;
172165
} else {
173-
left = mid + 1;
166+
l = mid + 1;
174167
}
175168
}
176-
return left;
169+
return l;
177170
};
178171
```
179172

180173
### **TypeScript**
181174

182175
```ts
183176
function findDuplicate(nums: number[]): number {
184-
let left = 1,
185-
right = nums.length - 1;
186-
while (left < right) {
187-
const mid = (left + right) >> 1;
177+
let l = 0;
178+
let r = nums.length - 1;
179+
while (l < r) {
180+
const mid = (l + r) >> 1;
188181
let cnt = 0;
189-
for (let v of nums) {
182+
for (const v of nums) {
190183
if (v <= mid) {
191184
++cnt;
192185
}
193186
}
194187
if (cnt > mid) {
195-
right = mid;
188+
r = mid;
196189
} else {
197-
left = mid + 1;
190+
l = mid + 1;
198191
}
199192
}
200-
return left;
193+
return l;
201194
}
202195
```
203196

solution/0200-0299/0287.Find the Duplicate Number/README_EN.md

Lines changed: 42 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -52,38 +52,33 @@
5252
```python
5353
class Solution:
5454
def findDuplicate(self, nums: List[int]) -> int:
55-
left, right = 1, len(nums) - 1
56-
while left < right:
57-
mid = (left + right) >> 1
58-
cnt = sum(v <= mid for v in nums)
59-
if cnt > mid:
60-
right = mid
61-
else:
62-
left = mid + 1
63-
return left
55+
def f(x: int) -> bool:
56+
return sum(v <= x for v in nums) > x
57+
58+
return bisect_left(range(len(nums)), True, key=f)
6459
```
6560

6661
### **Java**
6762

6863
```java
6964
class Solution {
7065
public int findDuplicate(int[] nums) {
71-
int left = 1, right = nums.length - 1;
72-
while (left < right) {
73-
int mid = (left + right) >> 1;
66+
int l = 0, r = nums.length - 1;
67+
while (l < r) {
68+
int mid = (l + r) >> 1;
7469
int cnt = 0;
7570
for (int v : nums) {
7671
if (v <= mid) {
7772
++cnt;
7873
}
7974
}
8075
if (cnt > mid) {
81-
right = mid;
76+
r = mid;
8277
} else {
83-
left = mid + 1;
78+
l = mid + 1;
8479
}
8580
}
86-
return left;
81+
return l;
8782
}
8883
}
8984
```
@@ -94,19 +89,20 @@ class Solution {
9489
class Solution {
9590
public:
9691
int findDuplicate(vector<int>& nums) {
97-
int left = 1, right = nums.size() - 1;
98-
while (left < right) {
99-
int mid = (left + right) >> 1;
92+
int l = 0, r = nums.size() - 1;
93+
while (l < r) {
94+
int mid = (l + r) >> 1;
10095
int cnt = 0;
101-
for (int& v : nums)
102-
if (v <= mid)
103-
++cnt;
104-
if (cnt > mid)
105-
right = mid;
106-
else
107-
left = mid + 1;
96+
for (int& v : nums) {
97+
cnt += v <= mid;
98+
}
99+
if (cnt > mid) {
100+
r = mid;
101+
} else {
102+
l = mid + 1;
103+
}
108104
}
109-
return left;
105+
return l;
110106
}
111107
};
112108
```
@@ -115,22 +111,15 @@ public:
115111
116112
```go
117113
func findDuplicate(nums []int) int {
118-
left, right := 1, len(nums)-1
119-
for left < right {
120-
mid := (left + right) >> 1
114+
return sort.Search(len(nums), func(x int) bool {
121115
cnt := 0
122116
for _, v := range nums {
123-
if v <= mid {
117+
if v <= x {
124118
cnt++
125119
}
126120
}
127-
if cnt > mid {
128-
right = mid
129-
} else {
130-
left = mid + 1
131-
}
132-
}
133-
return left
121+
return cnt > x
122+
})
134123
}
135124
```
136125

@@ -142,47 +131,47 @@ func findDuplicate(nums []int) int {
142131
* @return {number}
143132
*/
144133
var findDuplicate = function (nums) {
145-
let left = 1,
146-
right = nums.length - 1;
147-
while (left < right) {
148-
const mid = (left + right) >> 1;
134+
let l = 0;
135+
let r = nums.length - 1;
136+
while (l < r) {
137+
const mid = (l + r) >> 1;
149138
let cnt = 0;
150-
for (let v of nums) {
139+
for (const v of nums) {
151140
if (v <= mid) {
152141
++cnt;
153142
}
154143
}
155144
if (cnt > mid) {
156-
right = mid;
145+
r = mid;
157146
} else {
158-
left = mid + 1;
147+
l = mid + 1;
159148
}
160149
}
161-
return left;
150+
return l;
162151
};
163152
```
164153

165154
### **TypeScript**
166155

167156
```ts
168157
function findDuplicate(nums: number[]): number {
169-
let left = 1,
170-
right = nums.length - 1;
171-
while (left < right) {
172-
const mid = (left + right) >> 1;
158+
let l = 0;
159+
let r = nums.length - 1;
160+
while (l < r) {
161+
const mid = (l + r) >> 1;
173162
let cnt = 0;
174-
for (let v of nums) {
163+
for (const v of nums) {
175164
if (v <= mid) {
176165
++cnt;
177166
}
178167
}
179168
if (cnt > mid) {
180-
right = mid;
169+
r = mid;
181170
} else {
182-
left = mid + 1;
171+
l = mid + 1;
183172
}
184173
}
185-
return left;
174+
return l;
186175
}
187176
```
188177

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
11
class Solution {
22
public:
33
int findDuplicate(vector<int>& nums) {
4-
int left = 1, right = nums.size() - 1;
5-
while (left < right) {
6-
int mid = (left + right) >> 1;
4+
int l = 0, r = nums.size() - 1;
5+
while (l < r) {
6+
int mid = (l + r) >> 1;
77
int cnt = 0;
8-
for (int& v : nums)
9-
if (v <= mid)
10-
++cnt;
11-
if (cnt > mid)
12-
right = mid;
13-
else
14-
left = mid + 1;
8+
for (int& v : nums) {
9+
cnt += v <= mid;
10+
}
11+
if (cnt > mid) {
12+
r = mid;
13+
} else {
14+
l = mid + 1;
15+
}
1516
}
16-
return left;
17+
return l;
1718
}
1819
};

0 commit comments

Comments
 (0)