【剑指offer】JZ53 数字在升序数组中出现的次数

文章介绍了如何利用二分查找算法解决在一个非降序整数数组中找出给定整数k出现次数的问题,通过查找k+0.5和k-0.5的位置来确定k的实际出现次数,同时保证了空间复杂度为O(1)和时间复杂度为O(logn)。

1 问题

给定一个长度为 n 的非降序数组和一个非负数整数 k ,要求统计 k 在数组中出现的次数

数据范围:0≤n≤1000,0≤k≤100,数组中每个元素的值满足 0≤val≤100
要求:空间复杂度 O(1),时间复杂度 O(logn)

示例1
输入:[1,2,3,3,3,3,4,5],3
返回值:4

示例2
输入:[1,3,4,5],6
返回值:0

2 答案

自己写的不对,不能处理数组中数全相同的情况

class Solution:
    def GetNumberOfK(self , nums: List[int], k: int) -> int:
        if not nums:
            return 0
        if len(nums) == 1:
            if nums[0] == k:
                return 1
            else:
                return 0
        left = -1
        right = len(nums)
        while left + 1 < right:
            mid = left + (right - left) // 2
            if nums[mid] < k:
                left = mid
            else:
                right = mid
        res = 0
        while nums[right] == k:
            res+=1
            right+=1
        return res

官方解

因为data是一个非降序数组,它是有序的,这种时候我们可能会想到用二分查找。但是一个数组可能有多个k,而且我们要查找的并非常规二分法中k出现的位置,而是k出现的左界和k出现的右界。要是能刚好找到恰好小于k的数字位置和恰好大于k的数字的位置就好了。

再有因为数组中全是整数,因此我们可以考虑,用二分查找找到k+0.5应该出现的位置和k−0.5应该出现的位置,二者相减就是k出现的次数。

  • step 1:写一个二分查找的函数在数组中找到某个元素出现的位置。每次检查区间中点值,根据与中点的大小比较,确定下一次的区间。
  • step 2:分别使用二分查找,找到k+0.5和k-0.5应该出现的位置,中间的部分就全是k,相减计算次数就可以了。
class Solution:
    def bisearch(self, data: List[int], k: float) -> int:
        left = 0
        right = len(data) - 1
        while left <= right:
            mid = (right+left)//2
            if data[mid] < k:
                left = mid + 1
            elif data[mid] > k:
                right = mid - 1
        return left

    def GetNumberOfK(self , data: List[int], k: int) -> int:
        return self.bisearch(data, k + 0.5) - self.bisearch(data, k - 0.5)

https://www.nowcoder.com/share/jump/9318638301699688583204

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LouHerGetUp

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值