《剑指offer》----------------数字在排序数组中出现的次数

题目

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

方法一

暴力法 咔咔的循环就往上整就得了,但是违背了出题的本意,想考察你排序数组,没体现出来。但是好歹也算一个方法,写上去哈哈

代码

class Solution {
public:
    int GetNumberOfK(vector<int> data ,int k) {
        int n=data.size();
        int count=0;
        for(int i=0;i<n;i++)
        {
            if(k==data[i])
                count++;
        }
        return count;
    }
};

方法二

就是用C++ stl里面的lower_bound和upper_bound,lower_bound是找出不小于即大于等于的第一个数的下标 ;upper_bound是找出大于的第一个数的下标。
ower_bound( )和upper_bound( )都是利用二分查找的方法在一个排好序的数组中进行查找的。

在从小到大的排序数组中,

lower_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于或等于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。

upper_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。

代码

class Solution 
 2 {
 3 public:
 4     int GetNumberOfK(vector<int> data ,int k)
 5     {
 6         int s1 = lower_bound(data.begin(),data.end(),k)-data.begin();
 7         int s2 = upper_bound(data.begin(),data.end(),k)-data.begin();
           return s2-s1;
10     }
11 };

方法三

二分法 不断缩小范围
1.先找出第一次出现的下标值,设left,mid,right分别代表数组的起始,中间,结束的下标。

若数组中间的数a[mid]大于k,则right = mid -1;

若数组中间的数a[mid]小于k,则left = mid+1;

若数组中间的数a[mid]等于k,判断a[mid-1] 是否等于k,若不等于,说明是第一次出现的下标,返回mid下标;若等于,则说明第一次出现的下标还在mid的左边,right = mid -1;

递归重复以上过程。

2.再找出最后出现的下标,原理同上。

class Solution {
public:
      int GetNumberOfK(vector<int> data ,int k)
      {
          if(data.empty())
            return 0;
        int first=getFirst(data,0,data.size()-1,k);
        int last=getLast(data,0,data.size()-1,k);
          int count=0;
        if(first>-1&&last>-1)
            count=last-first+1;
            return count;
        
    }
     int getFirst(vector<int> data,int left,int right,int k){//用递归方式实现二分查找
        if(left>right)
            return -1;
          int mid=(left+right)/2;
        if (data[mid]==k)
        {
            if(mid>0&&data[mid-1]!=k||mid==0)
            {
                return mid;
            }
            else
                right=mid-1;
             
        }
        else if(data[mid]<k)
            left=mid+1;
        else
            right=mid-1;
        return getFirst(data,left,right,k);
    }
 
     int getLast(vector<int>data,int left,int right,int k)
    {
          if(left>right)
            return -1;
        int mid=(left+right)/2;
        
        if(data[mid]==k)
        {
            if(mid<data.size()-1&&data[mid+1]!=k||mid==data.size()-1)
                return mid;
            else
                left=mid+1;
        }
        else if(data[mid]<k)
            left=mid+1;
        else if(data[mid]>k)
            right=mid-1;
        return getLast(data,left,right,k);
    }
 
};

一定要注意,getFirst函数里如果不加上
if(left>right)
return -1;
编译是会报错,显示内存超出的;
我在这卡了半天才找到是这个原因。

发布了47 篇原创文章 · 获赞 2 · 访问量 1447

猜你喜欢

转载自blog.csdn.net/weixin_42076938/article/details/104169585