有序数组中的单一元素
难度:
标签:
题目描述
给你一个仅由整数组成的有序数组,其中每个元素都会出现两次,唯有一个数只会出现一次。
请你找出并返回只出现一次的那个数。
你设计的解决方案必须满足 O(log n)
时间复杂度和 O(1)
空间复杂度。
示例 1:
输入: nums = [1,1,2,3,3,4,4,8,8] 输出: 2
示例 2:
输入: nums = [3,3,7,7,10,11,11] 输出: 10
提示:
1 <= nums.length <= 105
0 <= nums[i] <= 105
代码结果
运行时间: 20 ms, 内存: 22.9 MB
/*
* 思路:
* 虽然题目要求O(log n)时间复杂度,通常使用二分查找。
* 但可以使用Java Stream结合数组进行二进制搜索。
* 这种方法更简洁但可能不满足题目对时间复杂度的严格要求。
*/
import java.util.Arrays;
import java.util.stream.IntStream;
public class Solution {
public int singleNonDuplicate(int[] nums) {
return IntStream.range(0, nums.length)
.filter(i -> i % 2 == 0 && (i == nums.length - 1 || nums[i] != nums[i + 1]))
.map(i -> nums[i])
.findFirst()
.orElse(-1); // 理论上不可能到达这个地方
}
}
解释
方法:
这个题解使用了二分查找的思路。因为数组是有序的,且除了一个元素只出现一次外其他元素都出现两次,所以可以利用元素的下标的奇偶性来缩小查找范围。如果 mid 是偶数下标,则比较 nums[mid] 和 nums[mid+1],如果两者相等,说明单一元素在 mid 之后,否则在 mid 及之前。如果 mid 是奇数下标,则比较 nums[mid] 和 nums[mid-1],如果两者相等,说明单一元素在 mid 之后,否则在 mid 及之前。最终 begin 和 end 会指向同一位置,即为单一元素的下标。
时间复杂度:
O(logn)
空间复杂度:
O(1)
代码细节讲解
🦆
在二分查找的过程中,为何当`mid`是偶数时比较`nums[mid]`和`nums[mid+1]`,而当`mid`是奇数时比较`nums[mid]`和`nums[mid-1]`?
▷🦆
题解中提到如果`nums[mid] == nums[mid+1]`则单一元素在`mid`之后,能否具体解释为什么这样判断会正确?
▷🦆
如果数组长度为奇数,二分查找的循环条件为`while begin < end`,在这种情况下循环是否会遗漏检查某些元素?
▷🦆
在二分查找过程结束时,为什么可以直接返回`nums[end]`作为结果,而不需要进一步验证?
▷