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

题目

在排好序的数组中,统计数k出现的次数

思路

思路一

使用二分查找,如果在中间出现,循环判断前一个数是否一样,后一个数是否一样,直到找到不一样的为止

思路二

先找到第一个k,再找最后一个k,下标相减得到计数
都使用二分查找,第一个k,如果k和中间值相等,那么要判断k是不是第一个,
前一个值是否是k,如果不是,那中间值就是第一个k;如果是k,那么去前半段找第一个k
最后一个同理

注意

二分查找中间值为(start+end) // 2,相加,不是相减
在循环中,要向前向后访问数组的值,记得先判断会不会越界。

代码

def GetNumberOfK(data, k):

    num = len(data)
    i = 0
    j = num - 1
    middle = num // 2
    count = 0
    while j-i >= 0:
        if data[middle] == k:
            count += 1
            n = middle - 1
            while n >=0 and data[n] == k:
                n -= 1
                count +=1
            m = middle + 1
            while m < num and data[m] == k:
                m +=1
                count +=1
            break
        elif data[middle] > k:
            j = middle - 1
        elif data[middle] < k:
            i = middle + 1
        middle = i + (j - i ) // 2
    return count

# 改进思路
def getfirstk(data,k):
    num = len(data)
    i = 0
    j = num - 1
    middle = num // 2
    while j-i >= 0:
        if data[middle] == k:
            if middle-1 >= 0 and data[middle-1] == k: # 向后向前遍历时,注意判断边界能不能取到
                j = middle -1
            else:
                return middle
        elif data[middle] > k:
            j = middle - 1
        elif data[middle] < k:
            i = middle + 1
        middle = (j + i ) // 2 # i + (j - i ) // 2
    return -1

def getlastk(data,k):
    num = len(data)
    i = 0
    j = num - 1
    middle = num // 2
    while j-i >= 0:
        if data[middle] == k:
            if middle+1 < num and data[middle+1] == k:
                i = middle + 1
            else:
                return middle
        elif data[middle] > k:
            j = middle - 1
        elif data[middle] < k:
            i = middle + 1
        middle = (j + i ) // 2 # i + (j - i ) // 2
    return -1

if __name__ == "__main__":
    data = [1,2,2,3,3,3,5,6,8,9]
    k = 1
    #print(GetNumberOfK(data,k))
    print(getlastk(data,k)-getfirstk(data,k)+1)
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值