第 k 个缺失的正整数与阿里3月8号面试题

题目描述

给你一个 严格升序排列 的正整数数组 arr 和一个整数 k 。请你找到这个数组里第 k 个缺失的正整数。

样例:
输入:arr = [2,3,4,7,11], k = 5
输出:9
解释:缺失的正整数包括 [1,5,6,8,9,10,12,13,…] 。
第 5 个缺失的正整数为 9 。

参考代码:

def findKthPositive(arr, k) :
    left=0
    right=len(arr)
    while left<right:
        mid = (left+right)//2
        if arr[mid]-mid-1>=k:
            right=mid
        else:
            left=mid+1
    return k+left

分析:

left:左边界
right:右边界
由样例可知数组arr是相对于整个正整数而言来计缺失的正整数,所以当数组arr确定时,它的最后一个数减去它的下标再减一(即arr[right]-right-1),就是到数组arr最后一个数一共缺失的整数的个数。

很容易想到该题可以使用二分查找的方法:
1、mid = (left+right)//2

2、当arr[mid]-mid-1>=k时,说明要找的第K个缺失的数在数组左边,所以right=mid(右边界替换)

3、当arr[mid]-mid-1<k时,说明要找的第K个缺失的数在数组右边,所以left=mid+1(左边界替换),这里的加一是因为要不满足 while left<right: 的循环条件退出,更重要的是保证第K个缺失的数在left最近的左边,所以往前加一。(补充:这里还要考虑一个特殊情况,要使mid等于arr下界,此时left=right,如果mid取下界时还是arr[mid]-mid-1<k,left+1越界,但循环不满足了,退出循环时正好保证第K个缺失的数在left最近的左边,虽然left是虚指了。)

4、当保证第K个缺失的数在left最近的左边时,要找的数就等于k加上left左边数的个数,正好是下标left的值,即k+left。

接下来我们来看一下阿里21年3月8号的面试题:

题目描述:

在这里插入图片描述

参考代码:

def findKthPositive(arr, k) :
    left=0
    right=len(arr)
    while left<right:
        mid = (left+right)//2
        if (arr[mid]-arr[0]+1)-(mid+1)>=k:
            right=mid
        else:
            left=mid+1
    return k+left+(arr[0]-1)

分析:

理解题目后,分析发现与前一题的差别仅仅在于起始数字的不同,前题目是从一开始,后题目是从arr[0]开始,所以计算arr[mid]到arr[0]一共缺失数字的个数就是;(arr[mid]-arr[0]+1)-(mid+1).

之后的返回值第K个缺失的数,就等于k+left再加上arr[0]之前缺失的数的个数就行了,即k+left+(arr[0]-1)。(或者理解为加上起始点)

总结:

二分法的关键就在于何时更新上限,何时更新下限,即找出最简洁的条件判断式;
再一个就是返回的结果尽量找一个最精简的式子,在写代码之前多找规律,多写式子,然后尝试套用模板,找出关键点。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值