剑指offer(牛客网) - 第38题 - 数字在排序数组中出现的次数

题目

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

解析

如何做到举一反三呢?这是个值得思考的问题,漠然忍受命运暴虐的毒箭,或是挺身反抗人世无涯的苦难,通过斗争把他扫清…跑题跑题啦!!
题目中出现 排序数组 时,我们应该直觉反应,可以使用二分查找算法。
因为是排序数组,所以我们可以找到出现指定数字的第一个位置和最后一个位置,从而来确定该数在数组中出现的次数。
如何找到第一次出现该数字的位置呢?
我们用二分查找,如果中间的数值是指定数,那么就判断前一个数是否是该数,若不是,该位置就是该数第一次出现的位置,此时还有一个特殊情况,若此时midIndex == 0 时,那么就不需要进行前一个位置的判断,0位置就是第一次出现的位置;如果中间位置的数值大于该数,说明该数出现的第一个位置在前半部分;反之,如果中间位置的数值小于该数,则说明该出第一次出现的位置在后半部分。
同理,我们可以得出该数的最后一次出现的位置。
至此,我们就能求出该数在这个排序数组中出现的次数。
这个算法的时间复杂度是 O(logn)。

Java 代码

public class Solution {
    public int GetNumberOfK(int [] array , int k) {
        int number = 0;
        if (array != null && array.length > 0) {
            int first = GetFirstOfK(array, 0, array.length - 1, k);
            int last = GetLastOfK(array, 0, array.length - 1, k);
            if (first > -1 && last > -1)
                number = last - first + 1;
        }
        return number;
    }

    private int GetFirstOfK(int [] array, int start, int end, int k) {
        if (start > end)
            return -1;

        int midindex = (start + end) / 2;
        int midIndexData = array[midindex];

        if (midIndexData == k) {
            if ((midindex > 0 && array[midindex - 1] != k) || midindex == 0)
                return midindex;
            else
                end = midindex - 1;
        } else if (midIndexData > k)
            end = midindex - 1;
        else
            start = midindex + 1;

        return GetFirstOfK(array,start,end,k);
    }
    private int GetLastOfK(int [] array, int start, int end, int k) {
        if (start > end)
            return -1;

        int midIndex = (start + end) / 2;
        int midIndexData = array[midIndex];

        if (midIndexData == k) {
            if ((midIndex < array.length - 1 && array[midIndex + 1] != k) || midIndex == array.length - 1)
                return midIndex;
            else
                start = midIndex + 1;
        } else if (midIndexData > k)
            end = midIndex - 1;
        else
            start = midIndex + 1;

        return GetLastOfK(array, start, end, k);
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值