Skip to content

Commit 8b55143

Browse files
authored
feat: add solutions to lc problem: No.0540 (#3735)
No.0540.Single Element in a Sorted Array
1 parent 02ee880 commit 8b55143

File tree

9 files changed

+153
-181
lines changed

9 files changed

+153
-181
lines changed

solution/0500-0599/0540.Single Element in a Sorted Array/README.md

+50-80
Original file line numberDiff line numberDiff line change
@@ -58,41 +58,15 @@ tags:
5858

5959
### 方法一:二分查找
6060

61-
给与的数组是有序的,由此可以使用二分查找,那条件该如何判断呢
61+
题目给定的数组 $\textit{nums}$ 是有序的,且要求在 $\textit{O}(\log n)$ 时间找到只出现一次的元素,因此我们考虑使用二分查找解决
6262

63-
先观察一下线性遍历是如何确定目标的:
63+
我们定义二分查找的左边界 $\textit{l} = 0$,右边界 $\textit{r} = n - 1$,其中 $n$ 是数组的长度。
6464

65-
```c
66-
for (int i = 0; i < n - 1; i += 2) {
67-
if (nums[i] != nums[i + 1]) {
68-
return nums[i];
69-
}
70-
}
71-
return nums[n - 1];
72-
```
65+
在每一步中,我们取中间位置 $\textit{mid} = (l + r) / 2$,如果下标 $\textit{mid}$ 为偶数,那么我们应该将 $\textit{nums}[\textit{mid}]$ 与 $\textit{nums}[\textit{mid} + 1]$ 进行比较;如果下标 $\textit{mid}$ 为奇数,那么我们应该将 $\textit{nums}[\textit{mid}]$ 与 $\textit{nums}[\textit{mid} - 1]$ 进行比较。因此,我们可以统一将 $\textit{nums}[\textit{mid}]$ 与 $\textit{nums}[\textit{mid} \oplus 1]$ 进行比较,其中 $\oplus$ 表示异或运算。
7366

74-
偶数下标:当 `nums[i] != nums[i + 1] && i % 2 == 0` 成立,结果便是 `nums[i]`
75-
奇数下标:当 `nums[i] != nums[i - 1] && i % 2 == 1` 成立,结果便是 `nums[i - 1]`
76-
77-
于是二分模板就有了:
78-
79-
```txt
80-
l = 0
81-
r = n - 1
82-
while l < r
83-
m = l + (r - l) / 2
84-
if m % 2 == 0
85-
if nums[m] == nums[m + 1]
86-
l = m + 1
87-
else
88-
r = m
89-
else
90-
if nums[m] == nums[m - 1]
91-
l = m + 1
92-
else
93-
r = m
94-
return nums[l]
95-
```
67+
如果 $\textit{nums}[\textit{mid}] \neq \textit{nums}[\textit{mid} \oplus 1]$,那么答案在 $[\textit{l}, \textit{mid}]$ 中,我们令 $\textit{r} = \textit{mid}$;如果 $\textit{nums}[\textit{mid}] = \textit{nums}[\textit{mid} \oplus 1]$,那么答案在 $[\textit{mid} + 1, \textit{r}]$ 中,我们令 $\textit{l} = \textit{mid} + 1$。继续二分查找,直到 $\textit{l} = \textit{r}$,此时 $\textit{nums}[\textit{l}]$ 即为只出现一次的元素。
68+
69+
时间复杂度 $\textit{O}(\log n)$,其中 $n$ 是数组 $\textit{nums}$ 的长度。空间复杂度 $\textit{O}(1)$。
9670

9771
<!-- tabs:start -->
9872

@@ -101,34 +75,31 @@ return nums[l]
10175
```python
10276
class Solution:
10377
def singleNonDuplicate(self, nums: List[int]) -> int:
104-
left, right = 0, len(nums) - 1
105-
while left < right:
106-
mid = (left + right) >> 1
107-
# Equals to: if (mid % 2 == 0 and nums[mid] != nums[mid + 1]) or (mid % 2 == 1 and nums[mid] != nums[mid - 1]):
78+
l, r = 0, len(nums) - 1
79+
while l < r:
80+
mid = (l + r) >> 1
10881
if nums[mid] != nums[mid ^ 1]:
109-
right = mid
82+
r = mid
11083
else:
111-
left = mid + 1
112-
return nums[left]
84+
l = mid + 1
85+
return nums[l]
11386
```
11487

11588
#### Java
11689

11790
```java
11891
class Solution {
11992
public int singleNonDuplicate(int[] nums) {
120-
int left = 0, right = nums.length - 1;
121-
while (left < right) {
122-
int mid = (left + right) >> 1;
123-
// if ((mid % 2 == 0 && nums[mid] != nums[mid + 1]) || (mid % 2 == 1 && nums[mid] !=
124-
// nums[mid - 1])) {
93+
int l = 0, r = nums.length - 1;
94+
while (l < r) {
95+
int mid = (l + r) >> 1;
12596
if (nums[mid] != nums[mid ^ 1]) {
126-
right = mid;
97+
r = mid;
12798
} else {
128-
left = mid + 1;
99+
l = mid + 1;
129100
}
130101
}
131-
return nums[left];
102+
return nums[l];
132103
}
133104
}
134105
```
@@ -139,15 +110,16 @@ class Solution {
139110
class Solution {
140111
public:
141112
int singleNonDuplicate(vector<int>& nums) {
142-
int left = 0, right = nums.size() - 1;
143-
while (left < right) {
144-
int mid = left + right >> 1;
145-
if (nums[mid] != nums[mid ^ 1])
146-
right = mid;
147-
else
148-
left = mid + 1;
113+
int l = 0, r = nums.size() - 1;
114+
while (l < r) {
115+
int mid = (l + r) >> 1;
116+
if (nums[mid] != nums[mid ^ 1]) {
117+
r = mid;
118+
} else {
119+
l = mid + 1;
120+
}
149121
}
150-
return nums[left];
122+
return nums[l];
151123
}
152124
};
153125
```
@@ -156,34 +128,33 @@ public:
156128
157129
```go
158130
func singleNonDuplicate(nums []int) int {
159-
left, right := 0, len(nums)-1
160-
for left < right {
161-
mid := (left + right) >> 1
131+
l, r := 0, len(nums)-1
132+
for l < r {
133+
mid := (l + r) >> 1
162134
if nums[mid] != nums[mid^1] {
163-
right = mid
135+
r = mid
164136
} else {
165-
left = mid + 1
137+
l = mid + 1
166138
}
167139
}
168-
return nums[left]
140+
return nums[l]
169141
}
170142
```
171143

172144
#### TypeScript
173145

174146
```ts
175147
function singleNonDuplicate(nums: number[]): number {
176-
let left = 0,
177-
right = nums.length - 1;
178-
while (left < right) {
179-
const mid = (left + right) >> 1;
180-
if (nums[mid] != nums[mid ^ 1]) {
181-
right = mid;
148+
let [l, r] = [0, nums.length - 1];
149+
while (l < r) {
150+
const mid = (l + r) >> 1;
151+
if (nums[mid] !== nums[mid ^ 1]) {
152+
r = mid;
182153
} else {
183-
left = mid + 1;
154+
l = mid + 1;
184155
}
185156
}
186-
return nums[left];
157+
return nums[l];
187158
}
188159
```
189160

@@ -196,10 +167,10 @@ impl Solution {
196167
let mut r = nums.len() - 1;
197168
while l < r {
198169
let mid = (l + r) >> 1;
199-
if nums[mid] == nums[mid ^ 1] {
200-
l = mid + 1;
201-
} else {
170+
if nums[mid] != nums[mid ^ 1] {
202171
r = mid;
172+
} else {
173+
l = mid + 1;
203174
}
204175
}
205176
nums[l]
@@ -211,17 +182,16 @@ impl Solution {
211182

212183
```c
213184
int singleNonDuplicate(int* nums, int numsSize) {
214-
int left = 0;
215-
int right = numsSize - 1;
216-
while (left < right) {
217-
int mid = left + (right - left) / 2;
218-
if (nums[mid] == nums[mid ^ 1]) {
219-
left = mid + 1;
185+
int l = 0, r = numsSize - 1;
186+
while (l < r) {
187+
int mid = (l + r) >> 1;
188+
if (nums[mid] != nums[mid ^ 1]) {
189+
r = mid;
220190
} else {
221-
right = mid;
191+
l = mid + 1;
222192
}
223193
}
224-
return nums[left];
194+
return nums[l];
225195
}
226196
```
227197

solution/0500-0599/0540.Single Element in a Sorted Array/README_EN.md

+55-49
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,17 @@ tags:
4545

4646
<!-- solution:start -->
4747

48-
### Solution 1
48+
### Solution 1: Binary Search
49+
50+
The given array $\textit{nums}$ is sorted, and we need to find the element that appears only once in $\textit{O}(\log n)$ time. Therefore, we consider using binary search to solve this problem.
51+
52+
We define the left boundary of the binary search as $\textit{l} = 0$ and the right boundary as $\textit{r} = n - 1$, where $n$ is the length of the array.
53+
54+
In each step, we take the middle position $\textit{mid} = (l + r) / 2$. If the index $\textit{mid}$ is even, we should compare $\textit{nums}[\textit{mid}]$ with $\textit{nums}[\textit{mid} + 1]$. If the index $\textit{mid}$ is odd, we should compare $\textit{nums}[\textit{mid}]$ with $\textit{nums}[\textit{mid} - 1]$. Therefore, we can uniformly compare $\textit{nums}[\textit{mid}]$ with $\textit{nums}[\textit{mid} \oplus 1]$, where $\oplus$ denotes the XOR operation.
55+
56+
If $\textit{nums}[\textit{mid}] \neq \textit{nums}[\textit{mid} \oplus 1]$, then the answer is in $[\textit{l}, \textit{mid}]$, so we set $\textit{r} = \textit{mid}$. If $\textit{nums}[\textit{mid}] = \textit{nums}[\textit{mid} \oplus 1]$, then the answer is in $[\textit{mid} + 1, \textit{r}]$, so we set $\textit{l} = \textit{mid} + 1$. We continue the binary search until $\textit{l} = \textit{r}$, at which point $\textit{nums}[\textit{l}]$ is the element that appears only once.
57+
58+
The time complexity is $\textit{O}(\log n)$, where $n$ is the length of the array $\textit{nums}$. The space complexity is $\textit{O}(1)$.
4959

5060
<!-- tabs:start -->
5161

@@ -54,34 +64,31 @@ tags:
5464
```python
5565
class Solution:
5666
def singleNonDuplicate(self, nums: List[int]) -> int:
57-
left, right = 0, len(nums) - 1
58-
while left < right:
59-
mid = (left + right) >> 1
60-
# Equals to: if (mid % 2 == 0 and nums[mid] != nums[mid + 1]) or (mid % 2 == 1 and nums[mid] != nums[mid - 1]):
67+
l, r = 0, len(nums) - 1
68+
while l < r:
69+
mid = (l + r) >> 1
6170
if nums[mid] != nums[mid ^ 1]:
62-
right = mid
71+
r = mid
6372
else:
64-
left = mid + 1
65-
return nums[left]
73+
l = mid + 1
74+
return nums[l]
6675
```
6776

6877
#### Java
6978

7079
```java
7180
class Solution {
7281
public int singleNonDuplicate(int[] nums) {
73-
int left = 0, right = nums.length - 1;
74-
while (left < right) {
75-
int mid = (left + right) >> 1;
76-
// if ((mid % 2 == 0 && nums[mid] != nums[mid + 1]) || (mid % 2 == 1 && nums[mid] !=
77-
// nums[mid - 1])) {
82+
int l = 0, r = nums.length - 1;
83+
while (l < r) {
84+
int mid = (l + r) >> 1;
7885
if (nums[mid] != nums[mid ^ 1]) {
79-
right = mid;
86+
r = mid;
8087
} else {
81-
left = mid + 1;
88+
l = mid + 1;
8289
}
8390
}
84-
return nums[left];
91+
return nums[l];
8592
}
8693
}
8794
```
@@ -92,15 +99,16 @@ class Solution {
9299
class Solution {
93100
public:
94101
int singleNonDuplicate(vector<int>& nums) {
95-
int left = 0, right = nums.size() - 1;
96-
while (left < right) {
97-
int mid = left + right >> 1;
98-
if (nums[mid] != nums[mid ^ 1])
99-
right = mid;
100-
else
101-
left = mid + 1;
102+
int l = 0, r = nums.size() - 1;
103+
while (l < r) {
104+
int mid = (l + r) >> 1;
105+
if (nums[mid] != nums[mid ^ 1]) {
106+
r = mid;
107+
} else {
108+
l = mid + 1;
109+
}
102110
}
103-
return nums[left];
111+
return nums[l];
104112
}
105113
};
106114
```
@@ -109,34 +117,33 @@ public:
109117
110118
```go
111119
func singleNonDuplicate(nums []int) int {
112-
left, right := 0, len(nums)-1
113-
for left < right {
114-
mid := (left + right) >> 1
120+
l, r := 0, len(nums)-1
121+
for l < r {
122+
mid := (l + r) >> 1
115123
if nums[mid] != nums[mid^1] {
116-
right = mid
124+
r = mid
117125
} else {
118-
left = mid + 1
126+
l = mid + 1
119127
}
120128
}
121-
return nums[left]
129+
return nums[l]
122130
}
123131
```
124132

125133
#### TypeScript
126134

127135
```ts
128136
function singleNonDuplicate(nums: number[]): number {
129-
let left = 0,
130-
right = nums.length - 1;
131-
while (left < right) {
132-
const mid = (left + right) >> 1;
133-
if (nums[mid] != nums[mid ^ 1]) {
134-
right = mid;
137+
let [l, r] = [0, nums.length - 1];
138+
while (l < r) {
139+
const mid = (l + r) >> 1;
140+
if (nums[mid] !== nums[mid ^ 1]) {
141+
r = mid;
135142
} else {
136-
left = mid + 1;
143+
l = mid + 1;
137144
}
138145
}
139-
return nums[left];
146+
return nums[l];
140147
}
141148
```
142149

@@ -149,10 +156,10 @@ impl Solution {
149156
let mut r = nums.len() - 1;
150157
while l < r {
151158
let mid = (l + r) >> 1;
152-
if nums[mid] == nums[mid ^ 1] {
153-
l = mid + 1;
154-
} else {
159+
if nums[mid] != nums[mid ^ 1] {
155160
r = mid;
161+
} else {
162+
l = mid + 1;
156163
}
157164
}
158165
nums[l]
@@ -164,17 +171,16 @@ impl Solution {
164171

165172
```c
166173
int singleNonDuplicate(int* nums, int numsSize) {
167-
int left = 0;
168-
int right = numsSize - 1;
169-
while (left < right) {
170-
int mid = left + (right - left) / 2;
171-
if (nums[mid] == nums[mid ^ 1]) {
172-
left = mid + 1;
174+
int l = 0, r = numsSize - 1;
175+
while (l < r) {
176+
int mid = (l + r) >> 1;
177+
if (nums[mid] != nums[mid ^ 1]) {
178+
r = mid;
173179
} else {
174-
right = mid;
180+
l = mid + 1;
175181
}
176182
}
177-
return nums[left];
183+
return nums[l];
178184
}
179185
```
180186

0 commit comments

Comments
 (0)