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

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

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

思路

  • 解法一
    词典解法。key为数字,value为出现的次数。未考虑数组的排序特性。
  • 解法二
    二分法思想。由于数组是有序的,只需要寻找到该数字在数组中首次出现的first_index和最后一次出现的last_index,即可得到出现的次数为last_index-first_index+1。
    在有序数组中寻找first_index和last_index都是基于二分查找的思想。以查找first_index为例:
    如果data[mid]<k,舍弃前半部分,begin = mid+1,mid = (begin+mid)//2,继续比较查找;
    如果data[mid]>k, 说明k必在前半部分,如果data[begin]==k,直接返回,否则end = mid,mid = (begin+mid)//2,继续比较查找;
    如果data[mid]==k,需要向前迭代,直到data[mid-1]!=k,确定first_index.

代码

  • 解法一
class Solution:
    def GetNumberOfK(self, data, k):                          #复杂度O(n)
        """Dict版本"""
        temp = {}
        for i in data:
            temp[i] = temp.get(i,0)+1
        return temp.get(k,0)
  • 解法二
class Solution:
    def GetNumberOfK(self, data, k):                            #复杂度为O(logn)
        if not data or not k:
            return 0
        if data[-1] == data[0] == k:                            #特殊情况[1,1,1,1],data是list顺序表,查找是O(1)
            return len(data)
        frist = self.getFrist(data,k)
        last = self.getLast(data, k)
        if frist > -1 and last > -1:
            return last - frist + 1
        return 0

    def getFrist(self, data, k):
        """二分查找数组中k的第一位"""
        begin = 0
        end = len(data) - 1
        mid = int((begin + end)/2)
        while begin <= end:
            if data[mid] < k:
                begin = mid + 1
            elif data[mid] > k:
                if k == data[begin]:                            #当k在前半段时,判断首元素是否是k,如果是直接返回
                    return begin
                end = mid - 1
            else:
                if mid <= begin or data[mid-1] != k:            #mid-1是否等于k,不等于说明mid就是第一个等于k的下标,等于就要往前考虑
                    return mid
                else:                              
                    end = mid - 1
            mid = int((begin + end)/2)
        return -1

    def getLast(self, data, k):
        """二分查找数组中k的最后一位"""
        begin = 0
        end = len(data) - 1
        mid = int((begin + end)/2)
        while begin <= end:
            if data[mid] < k:
                if data[end] == k:                              #当k在后半段时,判断尾元素是否是k,如果是直接返回
                    return end
                begin = mid + 1
            elif data[mid] > k:
                end = mid - 1
            else:
                if mid >= end or data[mid+1] != k:
                    return mid
                else:
                    begin = mid + 1
            mid = int((begin + end)/2)
        return -1

if __name__ = "__main__":
    data = [1,3,3,3,3,4,5]
    k = 2
    Solution().GetNumberOfK(data,k)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值