本文记录三道关于缺失元素的问题。
1. offer53-II 0~n-1中缺失的数字
// offer53-II 0~n-1中缺失的数字
// 输入: [0,1,3]
// 输出: 2
// 二分法:如果nums[mid] == mid 去右侧查找,否则去左侧查找
func find2(nums []int) int {
left, right := 0, len(nums) - 1
for left <= right {
mid := left + (right - left) / 2
if nums[mid] == mid {
left = mid + 1
} else {
right = mid - 1
}
}
return left
}
2. 第 k 个缺失的正整数
package main
// leetcode1539. 第k个缺失的正整数
// 输入:arr = [2,3,4,7,11], k = 5
// 输出:9
// 解释:缺失的正整数包括 [1,5,6,8,9,10,12,13,...] 。第 5 个缺失的正整数为 9 。
// 根据数组中每个数所对应的缺失的数的个数来考虑
func find1(nums []int, k int) int {
for i := 0; i < len(nums); i++ {
if nums[i] - i - 1 >= k {
return k + i
}
}
return k + len(nums)
}
3. leetcode1060 有序数组中的缺失元素
// leetcode1060 有序数组中的缺失元素
// 输入:arr = [4,7,9,10], k = 3
// 输出:8
// 解释:缺失的正整数包括 [5,6,8,...] 。第 5 个缺失的正整数为 9 。
// 相邻元素做差,统计相邻元素间缺失的数的个数,并更新k
func find31(nums []int, k int) int {
var res int
//left, right := 0, len(nums)
for i := 0; i < len(nums) - 1; i++ {
if nums[i+1] - nums[i] - 1 < k {
k = k - (nums[i+1] - nums[i] - 1)
} else {
res = nums[i] + k
return res
}
}
return nums[len(nums)-1] + k
}
func find32(nums []int, k int) int {
left, right := 0, len(nums) - 1
for left <= right {
mid := left + (right - left) / 2
counter := countMissing(nums, mid)
if counter < k {
left = mid + 1
} else if counter > k {
right = mid - 1
} else {
return nums[mid] - 1
}
}
// nums[right]为 >k 左边的元素
// nums[right] + k 为如果right左侧没有缺失,应该的位置
return nums[right] + k - countMissing(nums, right)
}
func countMissing(nums []int, i int) int {
return nums[i] - nums[0] - i
}