Skip to content

Commit 8e18d65

Browse files
committed
feat: add solutions to lc problem: No.3289
1 parent ea00723 commit 8e18d65

File tree

7 files changed

+338
-0
lines changed

7 files changed

+338
-0
lines changed

solution/3200-3299/3289.The Two Sneaky Numbers of Digitville/README.md

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,4 +172,132 @@ function getSneakyNumbers(nums: number[]): number[] {
172172

173173
<!-- solution:end -->
174174

175+
<!-- solution:start -->
176+
177+
### 方法二:位运算
178+
179+
设数组 $\textit{nums}$ 的长度为 $n + 2$,其中包含 $0 \sim n - 1$ 的整数,且有两个数字出现了两次。
180+
181+
我们可以通过异或运算来找出这两个数字。首先,我们对数组 $\textit{nums}$ 中的所有数字以及 $0 \sim n - 1$ 的整数进行异或运算,得到的结果为这两个重复数字的异或值,记为 $xx$。
182+
183+
接下来,我们可以通过 $xx$ 找到这两个数字的某些特征,进而将它们分开。具体步骤如下:
184+
185+
1. 找到 $xx$ 的二进制表示中最低位或最高位的 $1$ 的位置,记为 $k$。这个位置表示这两个数字在该位上是不同的。
186+
2. 根据第 $k$ 位的值,将数组 $\textit{nums}$ 中的数字以及 $0 \sim n - 1$ 的整数分成两组:一组在第 $k$ 位上为 $0$,另一组在第 $k$ 位上为 $1$。然后分别对这两组数字进行异或运算,得到的结果即为这两个重复数字。
187+
188+
时间复杂度 $O(n)$,其中 $n$ 为数组 $\textit{nums}$ 的长度。空间复杂度 $O(1)$。
189+
190+
<!-- tabs:start -->
191+
192+
#### Python3
193+
194+
```python
195+
class Solution:
196+
def getSneakyNumbers(self, nums: List[int]) -> List[int]:
197+
n = len(nums) - 2
198+
xx = nums[n] ^ nums[n + 1]
199+
for i in range(n):
200+
xx ^= i ^ nums[i]
201+
k = xx.bit_length() - 1
202+
ans = [0, 0]
203+
for x in nums:
204+
ans[x >> k & 1] ^= x
205+
for i in range(n):
206+
ans[i >> k & 1] ^= i
207+
return ans
208+
```
209+
210+
#### Java
211+
212+
```java
213+
class Solution {
214+
public int[] getSneakyNumbers(int[] nums) {
215+
int n = nums.length - 2;
216+
int xx = nums[n] ^ nums[n + 1];
217+
for (int i = 0; i < n; ++i) {
218+
xx ^= i ^ nums[i];
219+
}
220+
int k = Integer.numberOfTrailingZeros(xx);
221+
int[] ans = new int[2];
222+
for (int x : nums) {
223+
ans[x >> k & 1] ^= x;
224+
}
225+
for (int i = 0; i < n; ++i) {
226+
ans[i >> k & 1] ^= i;
227+
}
228+
return ans;
229+
}
230+
}
231+
```
232+
233+
#### C++
234+
235+
```cpp
236+
class Solution {
237+
public:
238+
vector<int> getSneakyNumbers(vector<int>& nums) {
239+
int n = nums.size() - 2;
240+
int xx = nums[n] ^ nums[n + 1];
241+
for (int i = 0; i < n; ++i) {
242+
xx ^= i ^ nums[i];
243+
}
244+
int k = __builtin_ctz(xx);
245+
vector<int> ans(2);
246+
for (int x : nums) {
247+
ans[(x >> k) & 1] ^= x;
248+
}
249+
for (int i = 0; i < n; ++i) {
250+
ans[(i >> k) & 1] ^= i;
251+
}
252+
return ans;
253+
}
254+
};
255+
```
256+
257+
#### Go
258+
259+
```go
260+
func getSneakyNumbers(nums []int) []int {
261+
n := len(nums) - 2
262+
xx := nums[n] ^ nums[n+1]
263+
for i := 0; i < n; i++ {
264+
xx ^= i ^ nums[i]
265+
}
266+
k := bits.TrailingZeros(uint(xx))
267+
ans := make([]int, 2)
268+
for _, x := range nums {
269+
ans[(x>>k)&1] ^= x
270+
}
271+
for i := 0; i < n; i++ {
272+
ans[(i>>k)&1] ^= i
273+
}
274+
return ans
275+
}
276+
```
277+
278+
#### TypeScript
279+
280+
```ts
281+
function getSneakyNumbers(nums: number[]): number[] {
282+
const n = nums.length - 2;
283+
let xx = nums[n] ^ nums[n + 1];
284+
for (let i = 0; i < n; ++i) {
285+
xx ^= i ^ nums[i];
286+
}
287+
const k = Math.clz32(xx & -xx) ^ 31;
288+
const ans = [0, 0];
289+
for (const x of nums) {
290+
ans[(x >> k) & 1] ^= x;
291+
}
292+
for (let i = 0; i < n; ++i) {
293+
ans[(i >> k) & 1] ^= i;
294+
}
295+
return ans;
296+
}
297+
```
298+
299+
<!-- tabs:end -->
300+
301+
<!-- solution:end -->
302+
175303
<!-- problem:end -->

solution/3200-3299/3289.The Two Sneaky Numbers of Digitville/README_EN.md

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,4 +168,132 @@ function getSneakyNumbers(nums: number[]): number[] {
168168

169169
<!-- solution:end -->
170170

171+
<!-- solution:start -->
172+
173+
### Solution 2: Bit Manipulation
174+
175+
Let the length of array $\textit{nums}$ be $n + 2$, which contains integers from $0$ to $n - 1$, with two numbers appearing twice.
176+
177+
We can find these two numbers using XOR operations. First, we perform XOR operations on all numbers in array $\textit{nums}$ and the integers from $0$ to $n - 1$. The result is the XOR value of the two duplicate numbers, denoted as $xx$.
178+
179+
Next, we can find certain characteristics of these two numbers through $xx$ and separate them. The specific steps are as follows:
180+
181+
1. Find the position of the lowest bit or highest bit with value $1$ in the binary representation of $xx$, denoted as $k$. This position indicates that the two numbers differ at this bit.
182+
2. Based on the value of the $k$-th bit, divide the numbers in array $\textit{nums}$ and the integers from $0$ to $n - 1$ into two groups: one group with $0$ at the $k$-th bit, and another group with $1$ at the $k$-th bit. Then perform XOR operations on these two groups separately, and the results are the two duplicate numbers.
183+
184+
The time complexity is $O(n)$, where $n$ is the length of array $\textit{nums}$. The space complexity is $O(1)$.
185+
186+
<!-- tabs:start -->
187+
188+
#### Python3
189+
190+
```python
191+
class Solution:
192+
def getSneakyNumbers(self, nums: List[int]) -> List[int]:
193+
n = len(nums) - 2
194+
xx = nums[n] ^ nums[n + 1]
195+
for i in range(n):
196+
xx ^= i ^ nums[i]
197+
k = xx.bit_length() - 1
198+
ans = [0, 0]
199+
for x in nums:
200+
ans[x >> k & 1] ^= x
201+
for i in range(n):
202+
ans[i >> k & 1] ^= i
203+
return ans
204+
```
205+
206+
#### Java
207+
208+
```java
209+
class Solution {
210+
public int[] getSneakyNumbers(int[] nums) {
211+
int n = nums.length - 2;
212+
int xx = nums[n] ^ nums[n + 1];
213+
for (int i = 0; i < n; ++i) {
214+
xx ^= i ^ nums[i];
215+
}
216+
int k = Integer.numberOfTrailingZeros(xx);
217+
int[] ans = new int[2];
218+
for (int x : nums) {
219+
ans[x >> k & 1] ^= x;
220+
}
221+
for (int i = 0; i < n; ++i) {
222+
ans[i >> k & 1] ^= i;
223+
}
224+
return ans;
225+
}
226+
}
227+
```
228+
229+
#### C++
230+
231+
```cpp
232+
class Solution {
233+
public:
234+
vector<int> getSneakyNumbers(vector<int>& nums) {
235+
int n = nums.size() - 2;
236+
int xx = nums[n] ^ nums[n + 1];
237+
for (int i = 0; i < n; ++i) {
238+
xx ^= i ^ nums[i];
239+
}
240+
int k = __builtin_ctz(xx);
241+
vector<int> ans(2);
242+
for (int x : nums) {
243+
ans[(x >> k) & 1] ^= x;
244+
}
245+
for (int i = 0; i < n; ++i) {
246+
ans[(i >> k) & 1] ^= i;
247+
}
248+
return ans;
249+
}
250+
};
251+
```
252+
253+
#### Go
254+
255+
```go
256+
func getSneakyNumbers(nums []int) []int {
257+
n := len(nums) - 2
258+
xx := nums[n] ^ nums[n+1]
259+
for i := 0; i < n; i++ {
260+
xx ^= i ^ nums[i]
261+
}
262+
k := bits.TrailingZeros(uint(xx))
263+
ans := make([]int, 2)
264+
for _, x := range nums {
265+
ans[(x>>k)&1] ^= x
266+
}
267+
for i := 0; i < n; i++ {
268+
ans[(i>>k)&1] ^= i
269+
}
270+
return ans
271+
}
272+
```
273+
274+
#### TypeScript
275+
276+
```ts
277+
function getSneakyNumbers(nums: number[]): number[] {
278+
const n = nums.length - 2;
279+
let xx = nums[n] ^ nums[n + 1];
280+
for (let i = 0; i < n; ++i) {
281+
xx ^= i ^ nums[i];
282+
}
283+
const k = Math.clz32(xx & -xx) ^ 31;
284+
const ans = [0, 0];
285+
for (const x of nums) {
286+
ans[(x >> k) & 1] ^= x;
287+
}
288+
for (let i = 0; i < n; ++i) {
289+
ans[(i >> k) & 1] ^= i;
290+
}
291+
return ans;
292+
}
293+
```
294+
295+
<!-- tabs:end -->
296+
297+
<!-- solution:end -->
298+
171299
<!-- problem:end -->
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
class Solution {
2+
public:
3+
vector<int> getSneakyNumbers(vector<int>& nums) {
4+
int n = nums.size() - 2;
5+
int xx = nums[n] ^ nums[n + 1];
6+
for (int i = 0; i < n; ++i) {
7+
xx ^= i ^ nums[i];
8+
}
9+
int k = __builtin_ctz(xx);
10+
vector<int> ans(2);
11+
for (int x : nums) {
12+
ans[(x >> k) & 1] ^= x;
13+
}
14+
for (int i = 0; i < n; ++i) {
15+
ans[(i >> k) & 1] ^= i;
16+
}
17+
return ans;
18+
}
19+
};
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
func getSneakyNumbers(nums []int) []int {
2+
n := len(nums) - 2
3+
xx := nums[n] ^ nums[n+1]
4+
for i := 0; i < n; i++ {
5+
xx ^= i ^ nums[i]
6+
}
7+
k := bits.TrailingZeros(uint(xx))
8+
ans := make([]int, 2)
9+
for _, x := range nums {
10+
ans[(x>>k)&1] ^= x
11+
}
12+
for i := 0; i < n; i++ {
13+
ans[(i>>k)&1] ^= i
14+
}
15+
return ans
16+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
class Solution {
2+
public int[] getSneakyNumbers(int[] nums) {
3+
int n = nums.length - 2;
4+
int xx = nums[n] ^ nums[n + 1];
5+
for (int i = 0; i < n; ++i) {
6+
xx ^= i ^ nums[i];
7+
}
8+
int k = Integer.numberOfTrailingZeros(xx);
9+
int[] ans = new int[2];
10+
for (int x : nums) {
11+
ans[x >> k & 1] ^= x;
12+
}
13+
for (int i = 0; i < n; ++i) {
14+
ans[i >> k & 1] ^= i;
15+
}
16+
return ans;
17+
}
18+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
class Solution:
2+
def getSneakyNumbers(self, nums: List[int]) -> List[int]:
3+
n = len(nums) - 2
4+
xx = nums[n] ^ nums[n + 1]
5+
for i in range(n):
6+
xx ^= i ^ nums[i]
7+
k = xx.bit_length() - 1
8+
ans = [0, 0]
9+
for x in nums:
10+
ans[x >> k & 1] ^= x
11+
for i in range(n):
12+
ans[i >> k & 1] ^= i
13+
return ans
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
function getSneakyNumbers(nums: number[]): number[] {
2+
const n = nums.length - 2;
3+
let xx = nums[n] ^ nums[n + 1];
4+
for (let i = 0; i < n; ++i) {
5+
xx ^= i ^ nums[i];
6+
}
7+
const k = Math.clz32(xx & -xx) ^ 31;
8+
const ans = [0, 0];
9+
for (const x of nums) {
10+
ans[(x >> k) & 1] ^= x;
11+
}
12+
for (let i = 0; i < n; ++i) {
13+
ans[(i >> k) & 1] ^= i;
14+
}
15+
return ans;
16+
}

0 commit comments

Comments
 (0)