1.题目解析
题目来源:LCR173.点名——力扣
原名:剑指offer——0~n-1中消失的数字
测试用例
题目来源:153.寻找旋转排序数组中的最小值——力扣
测试用例
2.算法原理
点名
如果要寻找消失的数字,可以判断对应下标的数字是否和下标对应即可,根据这个定义可以将数据分为两段:规范段与不规范段
1.当mid指针落入不规范段,需要从右边缩小范围,因为mid可能直接指向结果,所以right只能更新到mid
2.当mid落入规范段,需要从左边缩小范围,可以将left直接更新为mid+1,不用担心遗漏数据
注意:如果缺少的是最后一个数字,需要特殊处理
细节:由于更新左右指针出现了mid+1,所以初始化mid时使用left+(right-left)/2即可,不用left+(right-left+1)/2,第二种使用的条件是更新左右指针出现mid-1
寻找旋转排序数组中的最小值
按照数组最后一个元素可以将数组分为两段,一段是大于最后一个元素的,另一段是小于最后一个元素的,即旋转上段与旋转下段
1.mid落入到旋转上段,说明最小值一定不在mid落入的一段,需要从左缩小范围,left可以更新为mid+1
2.mid落入旋转下段,说明最小值一定在mid落入的一段,需要从右边缩小范围,由于mid可能直接指向了结果,所以right只能更新到mid
细节:由于更新左右指针出现了mid+1,所以初始化mid时使用left+(right-left)/2即可,不用left+(right-left+1)/2,第二种使用的条件是更新左右指针出现mid-1
3.实战代码
点名
class Solution {
public:
int takeAttendance(vector<int>& records)
{
int left = 0,right = records.size() - 1;
while(left < right)
{
int mid = left + (right - left) / 2;
//落入规范段
if(records[mid] == mid)
{
left = mid + 1;
}
//落入不规范段
else
{
right = mid;
}
}
if(left == records[left])
{
return left + 1;
}
return left;
}
};
寻找旋转排序数组中的最小值
class Solution
{
public:
int findMin(vector<int>& nums)
{
int left = 0,right = nums.size() - 1;
while(left < right)
{
int mid = left + (right - left) / 2;
//落入旋转上段
if(nums[mid] > nums[nums.size() - 1])
{
left = mid + 1;
}
//落入旋转下段
else
{
right = mid;
}
}
return nums[left];
}
};