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

题目描述:

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


思路:

因为是排序数组,自然联想到二分查找算法,这样我们在二分的时候可能会获取多个相同的数字。就是说,中间那个位置的值可能刚好是统计的那个值,假设为k。那么k还有可能在前面或者后面出现,在这个基础上继续二分当然也是可以的,如果能够在使用二分查找算法的时候统计出第一个k和最后一个k出现的位置,那么k出现的次数自然就确定了。第一个k出现的位置,可以使用二分查找算法,如果中间位置的值刚好是k,那么继续比较中间位置前面位置的值是不是也是k,如果不是那么该中间位置就是第一个k出现的位置,如果中间位置的前一个位置的值也是k,那么说明第一个k肯定出现在前半部分,继续二分即可。那么寻找最后一个k出现的位置也是一样的道理,比较中间位置后面一个位置的值是不是也是k,如果是说明最后一个k肯定出现在后半部分,继续二分即可,如果不是k的话,那么中间位置就是最后一个k出现的位置了,因为是排序数组,那么后面一个位置的值如果都不是k的话,其他位置更加不可能是k了。


代码实现:

public class Solution {
    public int GetNumberOfK(int [] array , int k) {
        if(array==null||array.length==0) return 0;
        int count = 0;
        int firstIndexOfK = getFirstK(array,k,0,array.length-1);
        int lastIndexOfK = getLastK(array,k,0,array.length-1);
        if(firstIndexOfK>=0&&lastIndexOfK>=0){
            count = lastIndexOfK - firstIndexOfK+1;
        }
        return count;
    }
    private int getFirstK(int [] array,int k,int start,int end){
        if(start>end) return -1;
        int middleIndex = (start+end)/2;
        int middleData = array[middleIndex];
        if(middleData == k){
            if((middleIndex>0&&array[middleIndex-1]!=k)||middleIndex==0){
                return middleIndex;
            }else{
                end = middleIndex-1;
            }
        }else if(middleData>k){
            end = middleIndex-1;
        }else{
            start = middleIndex+1;
        }
        return getFirstK(array,k,start,end);
    }
    private int getLastK(int[] array, int k, int start, int end) {
        if (start > end) return -1;
        int middleIndex = (start + end) / 2;
        int middleData = array[middleIndex];
        if (middleData == k) {
            if ((middleIndex < array.length - 1 && array[middleIndex + 1] != k)
                    || middleIndex == array.length - 1) {
                return middleIndex;
            } else {
                start = middleIndex + 1;
            }
        } else if (middleData > k) {
            end = middleIndex - 1;
        } else {
            start = middleIndex + 1;
        }
        return getLastK(array, k, start, end);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值