剑指offer 53 数字在排序数组中出现的次数

题目描述

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

 思路:

仍然使用二分查找思想,尝试不使用两边扫描,便能找到第一个k和最后一个k

分析:当有数字和K相等时,我们先判断这个数字是不是第一个k。如果中间数字的前面一个数字不是K,则此时中间的数字刚好就是第一个k,同理,如果中间数字的后面一个数字不是K,那么中间的数字就是最后一个k

因为GetFirstK和GetLastK都是利用二分查找,所以总的时间复杂度O(logn)

代码:

class Solution {
public:
    int GetNumberOfK(vector<int> data ,int k) {
        int n=data.size();
        int number=0;
        if(n>0)
        {  
        int first=GetFirstK(data,k,0,n-1);
        int last=GetLastK(data,k,0,n-1);
        
        if(first>-1&&last>-1)
         number=last-first+1;
        }
        return number;
    }
    //第一个k的位置
      int GetFirstK(vector<int> data ,int k,int low,int high) {
        if(low>high)
        return -1;
        int mid=(low+high)/2;
          if(k==data[mid])
          {
               if((mid>0&&data[mid-1]!=k)||mid==0)
                return mid;
               else  
                high=mid-1;
          }
         else if(k>data[mid])
              low=mid+1;
         else  high=mid-1;
         return GetFirstK(data,k,low,high);
    }
      //最后一个k的位置
       int GetLastK(vector<int> data ,int k,int low,int high) {
        if(low>high)
        return -1;
        int mid=(low+high)/2;
         if(k==data[mid])
          {
               if((mid<data.size()-1&&data[mid+1]!=k)||mid==data.size()-1)
                return mid;
               else  
               low=mid+1;
          }
         else if(k>data[mid])
              low=mid+1;
         else  high=mid-1;
        return GetLastK(data,k,low,high);
    }
};

举一反三:

0~n-1中缺失的数字

一个长度为n-1的递增顺序数组中的所有数字都是唯一的,并且每个数字都在范围0~n-1之内。在范围0~n-1内的n个数字中有且只有一个数字不在该数组中,请找出这个数字。

思路一:

算出当前数组的数组和s1,和数字0~n-1之间的数字和(n(n-1)/2)s2,利用s2-s1就是不在数组中的数字。

时间复杂度O(N)

思路二:

1、由于数组是递增的,且每个数字都是在0~n-1之内,所以在不缺少任何数字的情况下,元素值和下标值应该是相等的。

2、记不在数组中的数字为m,则所有比m小的数字的下标都与他们的值相同,比m大的值下标都与其值相差1.

3、因此问题转化为找出数组中第一个元素值与其下标不相等的元素。

代码:

int GetMissingNumber(vector<int>num)

{

int n=num.size();

if(n==0)

return -1;

int left=0;

int right=n-1;

while(left<=right)

{
int mid=(left+right)/2;

if(num[mid]!=middle)

{   if(middle===0||num[mid-1]==mid-1)

   return mid;

   right=mid-1;

}

else left=mid+1;

}

if(left==n)

return n;

//无效输入,数组没有按照要求排序,或者有数字不在0~n-1范围之内

return -1;

}

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

假设一个单调递增的数组里的每个元素都是整数并且是唯一的。请编程实现一个函数,找出数组中任意一个数值等于其下标的元素。例如:在数组{-3,-1,1,3,5}中,数字3和它的下标相等。

思路:

由上一题得到启发,我们可以先分析数组{-3,-1,1,3,5},我们发现,元素值与其下标的差是递增且过0的,-3,-2,-1,0,1,当差值等于零时,就是我们想要的值。

因此,我们根据差值与0比较利于二分法找出元素值与下标相同的值。

 

代码:

int GetNumberSameAsIndex(vector<int>num)

{

int n=num.size();

if(n==0)

return -1;

int left=0;

int right=n-1;

while(left<=right)

{

int mid=(left+right)/2;

if(num[mid]-mid>0)

right=mid-1;

else if(num[mid]-mid<0)

left=mid+1;

else return mid;

}
return -1;

}

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值