diff --git a/solution/3200-3299/3289.The Two Sneaky Numbers of Digitville/README.md b/solution/3200-3299/3289.The Two Sneaky Numbers of Digitville/README.md index 9c0dbf4429d4b..aab5e2d521018 100644 --- a/solution/3200-3299/3289.The Two Sneaky Numbers of Digitville/README.md +++ b/solution/3200-3299/3289.The Two Sneaky Numbers of Digitville/README.md @@ -172,4 +172,132 @@ function getSneakyNumbers(nums: number[]): number[] { + + +### 方法二:位运算 + +设数组 $\textit{nums}$ 的长度为 $n + 2$,其中包含 $0 \sim n - 1$ 的整数,且有两个数字出现了两次。 + +我们可以通过异或运算来找出这两个数字。首先,我们对数组 $\textit{nums}$ 中的所有数字以及 $0 \sim n - 1$ 的整数进行异或运算,得到的结果为这两个重复数字的异或值,记为 $xx$。 + +接下来,我们可以通过 $xx$ 找到这两个数字的某些特征,进而将它们分开。具体步骤如下: + +1. 找到 $xx$ 的二进制表示中最低位或最高位的 $1$ 的位置,记为 $k$。这个位置表示这两个数字在该位上是不同的。 +2. 根据第 $k$ 位的值,将数组 $\textit{nums}$ 中的数字以及 $0 \sim n - 1$ 的整数分成两组:一组在第 $k$ 位上为 $0$,另一组在第 $k$ 位上为 $1$。然后分别对这两组数字进行异或运算,得到的结果即为这两个重复数字。 + +时间复杂度 $O(n)$,其中 $n$ 为数组 $\textit{nums}$ 的长度。空间复杂度 $O(1)$。 + + + +#### Python3 + +```python +class Solution: + def getSneakyNumbers(self, nums: List[int]) -> List[int]: + n = len(nums) - 2 + xx = nums[n] ^ nums[n + 1] + for i in range(n): + xx ^= i ^ nums[i] + k = xx.bit_length() - 1 + ans = [0, 0] + for x in nums: + ans[x >> k & 1] ^= x + for i in range(n): + ans[i >> k & 1] ^= i + return ans +``` + +#### Java + +```java +class Solution { + public int[] getSneakyNumbers(int[] nums) { + int n = nums.length - 2; + int xx = nums[n] ^ nums[n + 1]; + for (int i = 0; i < n; ++i) { + xx ^= i ^ nums[i]; + } + int k = Integer.numberOfTrailingZeros(xx); + int[] ans = new int[2]; + for (int x : nums) { + ans[x >> k & 1] ^= x; + } + for (int i = 0; i < n; ++i) { + ans[i >> k & 1] ^= i; + } + return ans; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + vector getSneakyNumbers(vector& nums) { + int n = nums.size() - 2; + int xx = nums[n] ^ nums[n + 1]; + for (int i = 0; i < n; ++i) { + xx ^= i ^ nums[i]; + } + int k = __builtin_ctz(xx); + vector ans(2); + for (int x : nums) { + ans[(x >> k) & 1] ^= x; + } + for (int i = 0; i < n; ++i) { + ans[(i >> k) & 1] ^= i; + } + return ans; + } +}; +``` + +#### Go + +```go +func getSneakyNumbers(nums []int) []int { + n := len(nums) - 2 + xx := nums[n] ^ nums[n+1] + for i := 0; i < n; i++ { + xx ^= i ^ nums[i] + } + k := bits.TrailingZeros(uint(xx)) + ans := make([]int, 2) + for _, x := range nums { + ans[(x>>k)&1] ^= x + } + for i := 0; i < n; i++ { + ans[(i>>k)&1] ^= i + } + return ans +} +``` + +#### TypeScript + +```ts +function getSneakyNumbers(nums: number[]): number[] { + const n = nums.length - 2; + let xx = nums[n] ^ nums[n + 1]; + for (let i = 0; i < n; ++i) { + xx ^= i ^ nums[i]; + } + const k = Math.clz32(xx & -xx) ^ 31; + const ans = [0, 0]; + for (const x of nums) { + ans[(x >> k) & 1] ^= x; + } + for (let i = 0; i < n; ++i) { + ans[(i >> k) & 1] ^= i; + } + return ans; +} +``` + + + + + diff --git a/solution/3200-3299/3289.The Two Sneaky Numbers of Digitville/README_EN.md b/solution/3200-3299/3289.The Two Sneaky Numbers of Digitville/README_EN.md index 9dfcc11e321c8..c97469ba8f15f 100644 --- a/solution/3200-3299/3289.The Two Sneaky Numbers of Digitville/README_EN.md +++ b/solution/3200-3299/3289.The Two Sneaky Numbers of Digitville/README_EN.md @@ -168,4 +168,132 @@ function getSneakyNumbers(nums: number[]): number[] { + + +### Solution 2: Bit Manipulation + +Let the length of array $\textit{nums}$ be $n + 2$, which contains integers from $0$ to $n - 1$, with two numbers appearing twice. + +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$. + +Next, we can find certain characteristics of these two numbers through $xx$ and separate them. The specific steps are as follows: + +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. +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. + +The time complexity is $O(n)$, where $n$ is the length of array $\textit{nums}$. The space complexity is $O(1)$. + + + +#### Python3 + +```python +class Solution: + def getSneakyNumbers(self, nums: List[int]) -> List[int]: + n = len(nums) - 2 + xx = nums[n] ^ nums[n + 1] + for i in range(n): + xx ^= i ^ nums[i] + k = xx.bit_length() - 1 + ans = [0, 0] + for x in nums: + ans[x >> k & 1] ^= x + for i in range(n): + ans[i >> k & 1] ^= i + return ans +``` + +#### Java + +```java +class Solution { + public int[] getSneakyNumbers(int[] nums) { + int n = nums.length - 2; + int xx = nums[n] ^ nums[n + 1]; + for (int i = 0; i < n; ++i) { + xx ^= i ^ nums[i]; + } + int k = Integer.numberOfTrailingZeros(xx); + int[] ans = new int[2]; + for (int x : nums) { + ans[x >> k & 1] ^= x; + } + for (int i = 0; i < n; ++i) { + ans[i >> k & 1] ^= i; + } + return ans; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + vector getSneakyNumbers(vector& nums) { + int n = nums.size() - 2; + int xx = nums[n] ^ nums[n + 1]; + for (int i = 0; i < n; ++i) { + xx ^= i ^ nums[i]; + } + int k = __builtin_ctz(xx); + vector ans(2); + for (int x : nums) { + ans[(x >> k) & 1] ^= x; + } + for (int i = 0; i < n; ++i) { + ans[(i >> k) & 1] ^= i; + } + return ans; + } +}; +``` + +#### Go + +```go +func getSneakyNumbers(nums []int) []int { + n := len(nums) - 2 + xx := nums[n] ^ nums[n+1] + for i := 0; i < n; i++ { + xx ^= i ^ nums[i] + } + k := bits.TrailingZeros(uint(xx)) + ans := make([]int, 2) + for _, x := range nums { + ans[(x>>k)&1] ^= x + } + for i := 0; i < n; i++ { + ans[(i>>k)&1] ^= i + } + return ans +} +``` + +#### TypeScript + +```ts +function getSneakyNumbers(nums: number[]): number[] { + const n = nums.length - 2; + let xx = nums[n] ^ nums[n + 1]; + for (let i = 0; i < n; ++i) { + xx ^= i ^ nums[i]; + } + const k = Math.clz32(xx & -xx) ^ 31; + const ans = [0, 0]; + for (const x of nums) { + ans[(x >> k) & 1] ^= x; + } + for (let i = 0; i < n; ++i) { + ans[(i >> k) & 1] ^= i; + } + return ans; +} +``` + + + + + diff --git a/solution/3200-3299/3289.The Two Sneaky Numbers of Digitville/Solution2.cpp b/solution/3200-3299/3289.The Two Sneaky Numbers of Digitville/Solution2.cpp new file mode 100644 index 0000000000000..5ee8ceec56239 --- /dev/null +++ b/solution/3200-3299/3289.The Two Sneaky Numbers of Digitville/Solution2.cpp @@ -0,0 +1,19 @@ +class Solution { +public: + vector getSneakyNumbers(vector& nums) { + int n = nums.size() - 2; + int xx = nums[n] ^ nums[n + 1]; + for (int i = 0; i < n; ++i) { + xx ^= i ^ nums[i]; + } + int k = __builtin_ctz(xx); + vector ans(2); + for (int x : nums) { + ans[(x >> k) & 1] ^= x; + } + for (int i = 0; i < n; ++i) { + ans[(i >> k) & 1] ^= i; + } + return ans; + } +}; diff --git a/solution/3200-3299/3289.The Two Sneaky Numbers of Digitville/Solution2.go b/solution/3200-3299/3289.The Two Sneaky Numbers of Digitville/Solution2.go new file mode 100644 index 0000000000000..b1a93f7578fa2 --- /dev/null +++ b/solution/3200-3299/3289.The Two Sneaky Numbers of Digitville/Solution2.go @@ -0,0 +1,16 @@ +func getSneakyNumbers(nums []int) []int { + n := len(nums) - 2 + xx := nums[n] ^ nums[n+1] + for i := 0; i < n; i++ { + xx ^= i ^ nums[i] + } + k := bits.TrailingZeros(uint(xx)) + ans := make([]int, 2) + for _, x := range nums { + ans[(x>>k)&1] ^= x + } + for i := 0; i < n; i++ { + ans[(i>>k)&1] ^= i + } + return ans +} diff --git a/solution/3200-3299/3289.The Two Sneaky Numbers of Digitville/Solution2.java b/solution/3200-3299/3289.The Two Sneaky Numbers of Digitville/Solution2.java new file mode 100644 index 0000000000000..e90cc0d5f6a47 --- /dev/null +++ b/solution/3200-3299/3289.The Two Sneaky Numbers of Digitville/Solution2.java @@ -0,0 +1,18 @@ +class Solution { + public int[] getSneakyNumbers(int[] nums) { + int n = nums.length - 2; + int xx = nums[n] ^ nums[n + 1]; + for (int i = 0; i < n; ++i) { + xx ^= i ^ nums[i]; + } + int k = Integer.numberOfTrailingZeros(xx); + int[] ans = new int[2]; + for (int x : nums) { + ans[x >> k & 1] ^= x; + } + for (int i = 0; i < n; ++i) { + ans[i >> k & 1] ^= i; + } + return ans; + } +} diff --git a/solution/3200-3299/3289.The Two Sneaky Numbers of Digitville/Solution2.py b/solution/3200-3299/3289.The Two Sneaky Numbers of Digitville/Solution2.py new file mode 100644 index 0000000000000..e5d9f17bbed04 --- /dev/null +++ b/solution/3200-3299/3289.The Two Sneaky Numbers of Digitville/Solution2.py @@ -0,0 +1,13 @@ +class Solution: + def getSneakyNumbers(self, nums: List[int]) -> List[int]: + n = len(nums) - 2 + xx = nums[n] ^ nums[n + 1] + for i in range(n): + xx ^= i ^ nums[i] + k = xx.bit_length() - 1 + ans = [0, 0] + for x in nums: + ans[x >> k & 1] ^= x + for i in range(n): + ans[i >> k & 1] ^= i + return ans diff --git a/solution/3200-3299/3289.The Two Sneaky Numbers of Digitville/Solution2.ts b/solution/3200-3299/3289.The Two Sneaky Numbers of Digitville/Solution2.ts new file mode 100644 index 0000000000000..d5ff24a6a31d9 --- /dev/null +++ b/solution/3200-3299/3289.The Two Sneaky Numbers of Digitville/Solution2.ts @@ -0,0 +1,16 @@ +function getSneakyNumbers(nums: number[]): number[] { + const n = nums.length - 2; + let xx = nums[n] ^ nums[n + 1]; + for (let i = 0; i < n; ++i) { + xx ^= i ^ nums[i]; + } + const k = Math.clz32(xx & -xx) ^ 31; + const ans = [0, 0]; + for (const x of nums) { + ans[(x >> k) & 1] ^= x; + } + for (let i = 0; i < n; ++i) { + ans[(i >> k) & 1] ^= i; + } + return ans; +}