力扣1539. 第 k 个缺失的正整数

这一题的大意是说给出一个数组,和一个整数k,这个数组是严格升序排列的,现在让我们找第k个缺失的正整数。

什么叫做第k个缺失的正整数呢?意思是数组应该是从自然数1开始1...2...3正常排列的,但现在有缺失的,让我们找第k个缺失的数是多少?

那么我们如何可以判断呢,题目上让用一个小于logn的算法,又因为是让求第K个缺失的数,很明显是用二分。

那么该怎么二分呢?

我们很容易发现要想判断某一数组中缺失多少个数,只需要用 arri-(i+1) (i从0开始)即可求得。

那么我们只需要找第一个大于等于k的数,那么在它的上一个数就是最后一个小于等于k的数,我们只需要用arrl-1+k-arrl-1-l即算出第k个缺失的数是多少。这里的l表示的是第一个大于等于k的数,而l-1表示的是最后一个小于等于k的数。

这里的第一个arrl-1表示从这个往后再加+k-arrl-1-l个数就是第k个缺失的数。

而k-arrl-1-l表示最后一个小于等于k的数之前已经缺失了这些数,但还没有达到k个,还差k-arrl-1-l个数就达到了缺失的第k个数,我们只需要用arrl-1+k-arrl-1-l即为第k个缺失的数,化简得 k+l

因此代码如下:

cpp 复制代码
class Solution {
public:
    int findKthPositive(vector<int>& arr, int k) {
        int l=0;
        int r=arr.size()-1;
        while(l<=r)
        {
            int mid=(l+r)/2;
            if(arr[mid]-mid-1>=k)
            {
                r=mid-1;
            }
            else
            {
                l=mid+1;
            }
        }
        if(l!=0)
         return (arr[l-1]+(k-(arr[l-1]-l)));
        else{
            return k;
        }
    }
};

或者

cpp 复制代码
class Solution {
public:
   
    int findKthPositive(vector<int>& arr, int k) {
        int l=0;
        int r=arr.size()-1;
       
        while(l<=r)
        {
            int mid=(l+r)/2;
            if(arr[mid]-mid-1>=k)
            {
                r=mid-1;
            }
            else
            {
                l=mid+1;
            }
        }
         return l+k;
        
    }
};

这一题很容易想到二分,想到找第一个大于等于k的数的位置,但对于第k个数是多少,我觉得很不好想,看题解都是return l+k,但说不清楚l+k的含义。

实际上l+k的含义就是arrl-1+k-arrl-1-l的数学化简,要理解还是要用arrl-1+k-arrl-1-l

arrl-1+k-arrl-1-l即算出第k个缺失的数是多少。

时间复杂度O(logn)

我们也可以直接找最后一个小于k的数的位置,然后直接用arrr+k-(arrr-(r+1))好理解。

cpp 复制代码
class Solution {
public:
    int findKthPositive(vector<int>& arr, int k) {
        int l=0;
        int r=arr.size()-1;
        while(l<=r)
        {
            int mid=(l+r)/2;
            if(arr[mid]-mid-1<k)
            {
                l=mid+1;
            }
            else
            {
                r=mid-1;
            }
        }
       //最后一个小于k的位置
      if(r==-1)
      {
        return k;
      }
      else
       return arr[r]+(k-(arr[r]-(r+1)));
    
    }
};

这里的r是最终指向的最后一个小于k的位置,这里是跟上面的l的意思是类似的。

我们直接用二分找到最后一个缺失数字小于k的位置用这个位置的值arrr+(k-(arrr-r-1)(还差多少个数字)从而表示出第k个缺失的数字。

为什么非要找最后一个小于k的位置或者第一个大于等于k的位置,关键就在于我们可以弄清楚 第k个数就在最后一个小于k的位置或者第一个大于等于k的位置之间,只需要在再原有的基础上加上还缺的数字个数即可。

相关推荐
广州灵眸科技有限公司7 小时前
xfce桌面旋转说明:基于灵眸科技EASY-EAI-Nano-TB
网络·网络协议·tcp/ip·算法·php
想要成为糕糕手7 小时前
NO.48 旋转图像 —— LeetCode 热题 100 面试导向深度解析
javascript·算法·面试
JieE2128 小时前
LeetCode 138 随机链表的复制|两种解法详解(哈希表 + 原地 O (1) 空间)
javascript·算法·面试
专注于ai算法的踩坑小达人8 小时前
时序预测主流模型综述
算法·lstm
HZZD_HZZD9 小时前
碳核查场景下能源计量数据精准采集与碳排放核算算法全链路实战:从智能电表协议适配到排放因子动态计算
算法·能源
饼干哥哥9 小时前
10.5% 深层转化、90%+ 新用户,ChatGPT Ads 值得吗?
算法·正则表达式·编程语言
Irissgwe9 小时前
算法之二分查找
数据结构·c++·算法·二分查找
亿牛云爬虫专家9 小时前
代理IP质量评估:如何建立一套代理IP的多维度评分与淘汰算法?
tcp/ip·算法·爬虫代理·延迟·免费代理ip·连通率·时效
zzz_23689 小时前
【Java实习面试算法冲刺】动态规划
java·算法·面试
小蒋学算法10 小时前
算法-滑动窗口最大值
数据结构·算法