题目描述
给定一个包含 n + 1
个整数的数组 nums
,其数字都在 [1, n]
范围内(包括 1
和 n
),可知至少存在一个重复的整数。
假设 nums
只有 一个重复的整数 ,返回 这个重复的数 。
你设计的解决方案必须 不修改 数组 nums 且只用常量级 O(1) 的额外空间。
示例 1:
输入: nums = [1,3,4,2,2]
输出: 2
示例 2:
输入: nums = [3,1,3,4,2]
输出: 3
示例 3 :
输入: nums = [3,3,3,3,3]
输出: 3
提示:
- 1 <= n <= 105
- nums.length == n + 1
- 1 <= nums[i] <= n
- nums 中 只有一个整数 出现两次或多次 ,其余整数均只出现 一次
代码及注释
func findDuplicate(nums []int) int {
// 初始化左右边界
left, right := 1, len(nums) - 1
// 使用二分查找
for left < right {
// 计算中间值
mid := (left + right) / 2
// 统计数组中小于等于中间值的数字的数量
count := 0
for _, num := range nums {
if num <= mid {
count++
}
}
// 根据统计结果更新左右边界
if count > mid {
right = mid
} else {
left = mid + 1
}
}
// 返回重复的数字
return left
}
代码解释
-
初始化左右边界:
left
初始化为1
,right
初始化为len(nums) - 1
,因为数组中的数字在[1, n]
范围内。 -
二分查找:在每一步中,计算中间值
mid
。 -
统计小于等于中间值的数字数量:遍历数组
nums
,统计小于等于mid
的数字的数量。 -
更新左右边界:如果
count > mid
,说明重复的数字在[left, mid]
范围内,更新right = mid
;否则,重复的数字在[mid + 1, right]
范围内,更新left = mid + 1
。
示例
对于数组 [1, 3, 4, 2, 2]
:
- 初始:
left = 1, right = 4, mid = 2
- 小于等于
2
的数字数量为4
,count > mid
,所以更新right = 2
- 小于等于
- 第二次:
left = 1, right = 2, mid = 1
- 小于等于
1
的数字数量为1
,count <= mid
,所以更新left = 2
- 小于等于
- 第三次:
left = 2, right = 2, mid = 2
- 小于等于
2
的数字数量为4
,count > mid
,所以更新right = 2
- 小于等于
- 最终
left
和right
都为2
,所以重复的数字是2
。