1539.第K个缺失的正整数

给你一个 严格升序排列 的正整数数组 arr 和一个整数 k 。

请你找到这个数组里第 k 个缺失的正整数。

示例 1:

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

我的想法:用一个2000个长的map存储数字出现的次数,出现为0就是缺失的。然后遍历它,第K个缺失的就是那个哈希下标。

class Solution {
public:
    int findKthPositive(vector<int>& arr, int k) {
        map<int,int>hash;
        int cnt=0;
        int ans;
        int n=arr.size();
        for(int i=0;i<2001;i++)
        {
            hash[i]=0;
        }

        for(int i=0;i<n;i++)
        {
            hash[arr[i]]++;
        }
        for(int i=1;i<2001;i++)
        {
            if(hash[i]==0)
            {
                cnt++;
            }
            if(cnt==k)
            {
                ans=i;
                break;
            }
        }
        return ans;

    }
};

但是很奇怪,明明是线性复杂度,却只击败了百分之5的人。

解法2:利用arr[i]与其下标i关系
不难发现,一个不缺失元素的序列,会有arr[i]=i+1这样的关系,而在缺失元素之后,会有arr[i]>i+1,简单移项可得 arr[i]-i-1 > 0,缺失一个的时候,相差1,两个则相差2,以此类推,缺失越多,两者差距越大,我们要找第k个缺失的,换言之,只要arr[i]-i-1 == k,我们便找到了题目要找的数字。

class Solution {
public:
int findKthPositive(vector& arr, int k) {
int i,n = arr.size();
for(i=0;i if(arr[i]-i-1>=k){
return k+i;
}
}
return k+i;//亦可写成:k+n,只不过写成k+i方便理解下面一个解法
}
};

二分查找
然而上述的解法没有用上题目给出的条件 严格升序排列,已经找出了 arr[i]-i-1 > 0关系之后,我们可以利用上述的线性查找的方式改为二分查找的方式。

class Solution {
public:
int findKthPositive(vector& arr, int k) {
int left = 0, right = arr.size(), mid = 0;
while(left mid = left + (right-left)/2;
if(arr[mid]-mid >= k+1){
right = mid;
}else{
left = mid + 1;
}
}
return k + left;
}
};

你可能感兴趣的:(leetcode刷题之哈希表,数据结构,算法)