[剑指offer-53]在排序数组中查找数字

[53]在排序数组中查找数字

数字在排序数组中出现的次数

题目

统计一个数字在排序数组中出现的次数。

例如输入排序数组[1,2,3,3,3,3,4,5]和数字 3 ,由于 3 在这个数组中出现了 4 次,因此输出 4

分析

整数二分

一般写二分的思考顺序是这样的:首先通过题目背景和check(mid)函数的逻辑,判断答案落在左半区间还是右半区间。
左右半区间的划分方式一共有两种:

  1. 中点mid属于左半区间,则左半区间是[l, mid],右半区间是[mid+1, r],更新方式是r = mid;或者 l = mid + 1,此时用第一个模板。
  2. 中点mid属于右半区间,则左半区间是[l, mid-1],右半区间是[mid, r],更新方式是r = mid - 1;或者 l = mid,此时用第二个模板。

思路

利用二分查找 找个第一个出现最后一个出现的索引,然后相减

  • 为了获得数字 k 第一次出现的位置,我们可以将数组中所有大于等于k 的都归为右边部分 left = mid,left指向k第一次出现的位置
  • 为了获得数字 k 最后一次出现的位置,我们可以将数组中所有 小于等于k 的都归为左边部分,right 最后出现k的位置

mid属于左半区,分界点在[mid+1,right]右半区

在这里插入图片描述

mid在右半区,答案在有半区[mid,right]

在这里插入图片描述

思路视频

在这里插入图片描述

代码

class Solution {
public:
    int getNumberOfK(vector<int>& nums , int k) {
        
        if(!nums.size())  return 0;
        
        int l1=0,r1=nums.size()-1;
        
        while(l1<r1)  // 左边点
        {
            int mid=l1+r1 >> 1;
            if(nums[mid]<k)  l1=mid+1;
            else r1 = mid;
        }
        
        
        int l2=0,r2=nums.size()-1;
        
        while(l2<r2)  // 右边点
        {
            int mid=l2+r2 >> 1;
            if(nums[mid]<=k)  l2=mid; 
            else r2 = mid-1;
        }
        
        if(nums[l1] != k && nums[l2] != k) return 0;

        return l2 - l1 + 1;
    }
};

0~n-1中缺失的数字

题目

一个长度为n-1的递增排序数组中的所有数字都是唯一的,并且每个数字都在范围0到n-1之内。

在范围0到n-1的n个数字中有且只有一个数字不在该数组中,请找出这个数字

思路

假设数组中第一个缺失的数是 x ,那么数组中的数如下图所示

蓝色部分都满足 nums[i]==i

红色部分不满足 nums[i]==i

在这里插入图片描述

i f ( n u m s [ m i d ] ! = m i d ) if(nums[mid] != mid) if(nums[mid]!=mid) , 答案 【下标 x 】在mid左边,且mid 属于左边区间

在这里插入图片描述

注意——另外要注意特殊情况:当所有数都满足nums[i] == i时,表示缺失的是 n。

思路视频

在这里插入图片描述

代码

class Solution {
public:
    int getMissingNumber(vector<int>& nums) {
        if (nums.empty()) return 0;

        int l = 0, r = nums.size() - 1;  //  l,r表示数组下标
        while (l < r)
        {
            int mid = l + r >> 1;
            if (nums[mid] != mid) r = mid;
            else l = mid + 1;
        }

        if (nums[r] == r) r ++ ;  // 考虑特殊情况
        return r;
    }
};

数组中数值和下标相等的元素

题目

假设一个单调递增的数组里的每个元素都是整数并且是唯一的。

请编程实现一个函数找出数组中任意一个数值等于其下标的元素。

例如,在数组[-3, -1, 1, 3, 5]中,数字3和它的下标相等

思路

n u m s [ i ] − i nums[i]-i nums[i]i

还为递增数列,利用二分法,寻找 0 元素

在这里插入图片描述

代码

class Solution {
public:
    int getNumberSameAsIndex(vector<int>& nums) {
        
        int l=0, r=nums.size()-1;
        while(l<r)
        {
            int mid = l + r+1 >> 1;
            
            if(nums[mid]-mid>0) r = mid-1;
            
            else l=mid;
        }
        if(nums[l]==l)  return nums[l];
        return -1;              
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值