diff --git a/solution/0500-0599/0540.Single Element in a Sorted Array/README.md b/solution/0500-0599/0540.Single Element in a Sorted Array/README.md index a547c11b30901..7fb4b7d2d563d 100644 --- a/solution/0500-0599/0540.Single Element in a Sorted Array/README.md +++ b/solution/0500-0599/0540.Single Element in a Sorted Array/README.md @@ -58,41 +58,15 @@ tags: ### 方法一:二分查找 -给与的数组是有序的,由此可以使用二分查找,那条件该如何判断呢。 +题目给定的数组 $\textit{nums}$ 是有序的,且要求在 $\textit{O}(\log n)$ 时间找到只出现一次的元素,因此我们考虑使用二分查找解决。 -先观察一下线性遍历是如何确定目标的: +我们定义二分查找的左边界 $\textit{l} = 0$,右边界 $\textit{r} = n - 1$,其中 $n$ 是数组的长度。 -```c -for (int i = 0; i < n - 1; i += 2) { - if (nums[i] != nums[i + 1]) { - return nums[i]; - } -} -return nums[n - 1]; -``` +在每一步中,我们取中间位置 $\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$ 表示异或运算。 -偶数下标:当 `nums[i] != nums[i + 1] && i % 2 == 0` 成立,结果便是 `nums[i]`。 -奇数下标:当 `nums[i] != nums[i - 1] && i % 2 == 1` 成立,结果便是 `nums[i - 1]`。 - -于是二分模板就有了: - -```txt -l = 0 -r = n - 1 -while l < r - m = l + (r - l) / 2 - if m % 2 == 0 - if nums[m] == nums[m + 1] - l = m + 1 - else - r = m - else - if nums[m] == nums[m - 1] - l = m + 1 - else - r = m -return nums[l] -``` +如果 $\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}]$ 即为只出现一次的元素。 + +时间复杂度 $\textit{O}(\log n)$,其中 $n$ 是数组 $\textit{nums}$ 的长度。空间复杂度 $\textit{O}(1)$。 @@ -101,15 +75,14 @@ return nums[l] ```python class Solution: def singleNonDuplicate(self, nums: List[int]) -> int: - left, right = 0, len(nums) - 1 - while left < right: - mid = (left + right) >> 1 - # Equals to: if (mid % 2 == 0 and nums[mid] != nums[mid + 1]) or (mid % 2 == 1 and nums[mid] != nums[mid - 1]): + l, r = 0, len(nums) - 1 + while l < r: + mid = (l + r) >> 1 if nums[mid] != nums[mid ^ 1]: - right = mid + r = mid else: - left = mid + 1 - return nums[left] + l = mid + 1 + return nums[l] ``` #### Java @@ -117,18 +90,16 @@ class Solution: ```java class Solution { public int singleNonDuplicate(int[] nums) { - int left = 0, right = nums.length - 1; - while (left < right) { - int mid = (left + right) >> 1; - // if ((mid % 2 == 0 && nums[mid] != nums[mid + 1]) || (mid % 2 == 1 && nums[mid] != - // nums[mid - 1])) { + int l = 0, r = nums.length - 1; + while (l < r) { + int mid = (l + r) >> 1; if (nums[mid] != nums[mid ^ 1]) { - right = mid; + r = mid; } else { - left = mid + 1; + l = mid + 1; } } - return nums[left]; + return nums[l]; } } ``` @@ -139,15 +110,16 @@ class Solution { class Solution { public: int singleNonDuplicate(vector& nums) { - int left = 0, right = nums.size() - 1; - while (left < right) { - int mid = left + right >> 1; - if (nums[mid] != nums[mid ^ 1]) - right = mid; - else - left = mid + 1; + int l = 0, r = nums.size() - 1; + while (l < r) { + int mid = (l + r) >> 1; + if (nums[mid] != nums[mid ^ 1]) { + r = mid; + } else { + l = mid + 1; + } } - return nums[left]; + return nums[l]; } }; ``` @@ -156,16 +128,16 @@ public: ```go func singleNonDuplicate(nums []int) int { - left, right := 0, len(nums)-1 - for left < right { - mid := (left + right) >> 1 + l, r := 0, len(nums)-1 + for l < r { + mid := (l + r) >> 1 if nums[mid] != nums[mid^1] { - right = mid + r = mid } else { - left = mid + 1 + l = mid + 1 } } - return nums[left] + return nums[l] } ``` @@ -173,17 +145,16 @@ func singleNonDuplicate(nums []int) int { ```ts function singleNonDuplicate(nums: number[]): number { - let left = 0, - right = nums.length - 1; - while (left < right) { - const mid = (left + right) >> 1; - if (nums[mid] != nums[mid ^ 1]) { - right = mid; + let [l, r] = [0, nums.length - 1]; + while (l < r) { + const mid = (l + r) >> 1; + if (nums[mid] !== nums[mid ^ 1]) { + r = mid; } else { - left = mid + 1; + l = mid + 1; } } - return nums[left]; + return nums[l]; } ``` @@ -196,10 +167,10 @@ impl Solution { let mut r = nums.len() - 1; while l < r { let mid = (l + r) >> 1; - if nums[mid] == nums[mid ^ 1] { - l = mid + 1; - } else { + if nums[mid] != nums[mid ^ 1] { r = mid; + } else { + l = mid + 1; } } nums[l] @@ -211,17 +182,16 @@ impl Solution { ```c int singleNonDuplicate(int* nums, int numsSize) { - int left = 0; - int right = numsSize - 1; - while (left < right) { - int mid = left + (right - left) / 2; - if (nums[mid] == nums[mid ^ 1]) { - left = mid + 1; + int l = 0, r = numsSize - 1; + while (l < r) { + int mid = (l + r) >> 1; + if (nums[mid] != nums[mid ^ 1]) { + r = mid; } else { - right = mid; + l = mid + 1; } } - return nums[left]; + return nums[l]; } ``` diff --git a/solution/0500-0599/0540.Single Element in a Sorted Array/README_EN.md b/solution/0500-0599/0540.Single Element in a Sorted Array/README_EN.md index 4098085e35066..d9c0b89625b67 100644 --- a/solution/0500-0599/0540.Single Element in a Sorted Array/README_EN.md +++ b/solution/0500-0599/0540.Single Element in a Sorted Array/README_EN.md @@ -45,7 +45,17 @@ tags: -### Solution 1 +### Solution 1: Binary Search + +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. + +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. + +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. + +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. + +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)$. @@ -54,15 +64,14 @@ tags: ```python class Solution: def singleNonDuplicate(self, nums: List[int]) -> int: - left, right = 0, len(nums) - 1 - while left < right: - mid = (left + right) >> 1 - # Equals to: if (mid % 2 == 0 and nums[mid] != nums[mid + 1]) or (mid % 2 == 1 and nums[mid] != nums[mid - 1]): + l, r = 0, len(nums) - 1 + while l < r: + mid = (l + r) >> 1 if nums[mid] != nums[mid ^ 1]: - right = mid + r = mid else: - left = mid + 1 - return nums[left] + l = mid + 1 + return nums[l] ``` #### Java @@ -70,18 +79,16 @@ class Solution: ```java class Solution { public int singleNonDuplicate(int[] nums) { - int left = 0, right = nums.length - 1; - while (left < right) { - int mid = (left + right) >> 1; - // if ((mid % 2 == 0 && nums[mid] != nums[mid + 1]) || (mid % 2 == 1 && nums[mid] != - // nums[mid - 1])) { + int l = 0, r = nums.length - 1; + while (l < r) { + int mid = (l + r) >> 1; if (nums[mid] != nums[mid ^ 1]) { - right = mid; + r = mid; } else { - left = mid + 1; + l = mid + 1; } } - return nums[left]; + return nums[l]; } } ``` @@ -92,15 +99,16 @@ class Solution { class Solution { public: int singleNonDuplicate(vector& nums) { - int left = 0, right = nums.size() - 1; - while (left < right) { - int mid = left + right >> 1; - if (nums[mid] != nums[mid ^ 1]) - right = mid; - else - left = mid + 1; + int l = 0, r = nums.size() - 1; + while (l < r) { + int mid = (l + r) >> 1; + if (nums[mid] != nums[mid ^ 1]) { + r = mid; + } else { + l = mid + 1; + } } - return nums[left]; + return nums[l]; } }; ``` @@ -109,16 +117,16 @@ public: ```go func singleNonDuplicate(nums []int) int { - left, right := 0, len(nums)-1 - for left < right { - mid := (left + right) >> 1 + l, r := 0, len(nums)-1 + for l < r { + mid := (l + r) >> 1 if nums[mid] != nums[mid^1] { - right = mid + r = mid } else { - left = mid + 1 + l = mid + 1 } } - return nums[left] + return nums[l] } ``` @@ -126,17 +134,16 @@ func singleNonDuplicate(nums []int) int { ```ts function singleNonDuplicate(nums: number[]): number { - let left = 0, - right = nums.length - 1; - while (left < right) { - const mid = (left + right) >> 1; - if (nums[mid] != nums[mid ^ 1]) { - right = mid; + let [l, r] = [0, nums.length - 1]; + while (l < r) { + const mid = (l + r) >> 1; + if (nums[mid] !== nums[mid ^ 1]) { + r = mid; } else { - left = mid + 1; + l = mid + 1; } } - return nums[left]; + return nums[l]; } ``` @@ -149,10 +156,10 @@ impl Solution { let mut r = nums.len() - 1; while l < r { let mid = (l + r) >> 1; - if nums[mid] == nums[mid ^ 1] { - l = mid + 1; - } else { + if nums[mid] != nums[mid ^ 1] { r = mid; + } else { + l = mid + 1; } } nums[l] @@ -164,17 +171,16 @@ impl Solution { ```c int singleNonDuplicate(int* nums, int numsSize) { - int left = 0; - int right = numsSize - 1; - while (left < right) { - int mid = left + (right - left) / 2; - if (nums[mid] == nums[mid ^ 1]) { - left = mid + 1; + int l = 0, r = numsSize - 1; + while (l < r) { + int mid = (l + r) >> 1; + if (nums[mid] != nums[mid ^ 1]) { + r = mid; } else { - right = mid; + l = mid + 1; } } - return nums[left]; + return nums[l]; } ``` diff --git a/solution/0500-0599/0540.Single Element in a Sorted Array/Solution.c b/solution/0500-0599/0540.Single Element in a Sorted Array/Solution.c index 0eb20cd2cd26e..ada4f5347f83e 100644 --- a/solution/0500-0599/0540.Single Element in a Sorted Array/Solution.c +++ b/solution/0500-0599/0540.Single Element in a Sorted Array/Solution.c @@ -1,13 +1,12 @@ int singleNonDuplicate(int* nums, int numsSize) { - int left = 0; - int right = numsSize - 1; - while (left < right) { - int mid = left + (right - left) / 2; - if (nums[mid] == nums[mid ^ 1]) { - left = mid + 1; + int l = 0, r = numsSize - 1; + while (l < r) { + int mid = (l + r) >> 1; + if (nums[mid] != nums[mid ^ 1]) { + r = mid; } else { - right = mid; + l = mid + 1; } } - return nums[left]; -} \ No newline at end of file + return nums[l]; +} diff --git a/solution/0500-0599/0540.Single Element in a Sorted Array/Solution.cpp b/solution/0500-0599/0540.Single Element in a Sorted Array/Solution.cpp index 5668de91bd506..b88e55c767bd0 100644 --- a/solution/0500-0599/0540.Single Element in a Sorted Array/Solution.cpp +++ b/solution/0500-0599/0540.Single Element in a Sorted Array/Solution.cpp @@ -1,14 +1,15 @@ class Solution { public: int singleNonDuplicate(vector& nums) { - int left = 0, right = nums.size() - 1; - while (left < right) { - int mid = left + right >> 1; - if (nums[mid] != nums[mid ^ 1]) - right = mid; - else - left = mid + 1; + int l = 0, r = nums.size() - 1; + while (l < r) { + int mid = (l + r) >> 1; + if (nums[mid] != nums[mid ^ 1]) { + r = mid; + } else { + l = mid + 1; + } } - return nums[left]; + return nums[l]; } -}; \ No newline at end of file +}; diff --git a/solution/0500-0599/0540.Single Element in a Sorted Array/Solution.go b/solution/0500-0599/0540.Single Element in a Sorted Array/Solution.go index 72b9ed074824d..5a81808b2fecb 100644 --- a/solution/0500-0599/0540.Single Element in a Sorted Array/Solution.go +++ b/solution/0500-0599/0540.Single Element in a Sorted Array/Solution.go @@ -1,12 +1,12 @@ func singleNonDuplicate(nums []int) int { - left, right := 0, len(nums)-1 - for left < right { - mid := (left + right) >> 1 + l, r := 0, len(nums)-1 + for l < r { + mid := (l + r) >> 1 if nums[mid] != nums[mid^1] { - right = mid + r = mid } else { - left = mid + 1 + l = mid + 1 } } - return nums[left] -} \ No newline at end of file + return nums[l] +} diff --git a/solution/0500-0599/0540.Single Element in a Sorted Array/Solution.java b/solution/0500-0599/0540.Single Element in a Sorted Array/Solution.java index 6a083d46bb07f..96de50e3f5758 100644 --- a/solution/0500-0599/0540.Single Element in a Sorted Array/Solution.java +++ b/solution/0500-0599/0540.Single Element in a Sorted Array/Solution.java @@ -1,16 +1,14 @@ class Solution { public int singleNonDuplicate(int[] nums) { - int left = 0, right = nums.length - 1; - while (left < right) { - int mid = (left + right) >> 1; - // if ((mid % 2 == 0 && nums[mid] != nums[mid + 1]) || (mid % 2 == 1 && nums[mid] != - // nums[mid - 1])) { + int l = 0, r = nums.length - 1; + while (l < r) { + int mid = (l + r) >> 1; if (nums[mid] != nums[mid ^ 1]) { - right = mid; + r = mid; } else { - left = mid + 1; + l = mid + 1; } } - return nums[left]; + return nums[l]; } -} \ No newline at end of file +} diff --git a/solution/0500-0599/0540.Single Element in a Sorted Array/Solution.py b/solution/0500-0599/0540.Single Element in a Sorted Array/Solution.py index 717db5372ddb6..48192d8bd59b5 100644 --- a/solution/0500-0599/0540.Single Element in a Sorted Array/Solution.py +++ b/solution/0500-0599/0540.Single Element in a Sorted Array/Solution.py @@ -1,11 +1,10 @@ class Solution: def singleNonDuplicate(self, nums: List[int]) -> int: - left, right = 0, len(nums) - 1 - while left < right: - mid = (left + right) >> 1 - # Equals to: if (mid % 2 == 0 and nums[mid] != nums[mid + 1]) or (mid % 2 == 1 and nums[mid] != nums[mid - 1]): + l, r = 0, len(nums) - 1 + while l < r: + mid = (l + r) >> 1 if nums[mid] != nums[mid ^ 1]: - right = mid + r = mid else: - left = mid + 1 - return nums[left] + l = mid + 1 + return nums[l] diff --git a/solution/0500-0599/0540.Single Element in a Sorted Array/Solution.rs b/solution/0500-0599/0540.Single Element in a Sorted Array/Solution.rs index 45cedbf2956d2..5b61a6e61c0a4 100644 --- a/solution/0500-0599/0540.Single Element in a Sorted Array/Solution.rs +++ b/solution/0500-0599/0540.Single Element in a Sorted Array/Solution.rs @@ -4,10 +4,10 @@ impl Solution { let mut r = nums.len() - 1; while l < r { let mid = (l + r) >> 1; - if nums[mid] == nums[mid ^ 1] { - l = mid + 1; - } else { + if nums[mid] != nums[mid ^ 1] { r = mid; + } else { + l = mid + 1; } } nums[l] diff --git a/solution/0500-0599/0540.Single Element in a Sorted Array/Solution.ts b/solution/0500-0599/0540.Single Element in a Sorted Array/Solution.ts index 248646a46544a..13ff4436648c0 100644 --- a/solution/0500-0599/0540.Single Element in a Sorted Array/Solution.ts +++ b/solution/0500-0599/0540.Single Element in a Sorted Array/Solution.ts @@ -1,13 +1,12 @@ function singleNonDuplicate(nums: number[]): number { - let left = 0, - right = nums.length - 1; - while (left < right) { - const mid = (left + right) >> 1; - if (nums[mid] != nums[mid ^ 1]) { - right = mid; + let [l, r] = [0, nums.length - 1]; + while (l < r) { + const mid = (l + r) >> 1; + if (nums[mid] !== nums[mid ^ 1]) { + r = mid; } else { - left = mid + 1; + l = mid + 1; } } - return nums[left]; + return nums[l]; }