【问题标题】:Kth missing positive integer第 K 个缺失的正整数
【发布时间】:2023-03-28 09:15:01
【问题描述】:

给定一个按严格递增顺序排序的正整数数组 arr 和一个整数 k。

查找此数组中缺少的第 k 个正整数。

示例 1:

输入:arr = [2,3,4,7,11], k = 5 输出:9 解释:缺少的正整数是 [1,5,6,8,9,10,12,13,...]。第 5 个缺失的正整数是 9。 示例 2:

输入:arr = [1,2,3,4], k = 2 输出:6 解释:缺少的正整数是 [5,6,7,...]。第二个缺失的正整数是 6。

约束:

1

1

1

arr[i]

我已提交此代码,但显示 TLE 错误。请解释为什么会发生 TLE 以及如何解决此问题。

    class Solution {
public:
    int findKthPositive(vector<int>& arr, int k) {
        vector<int> ans;
        int count=0,i=1,flag=0;
        
        while(count<k)
        {
            int start=0,end=arr.size()-1;
            while(start<=end)
            {
                int mid=start+(end-start)/2;
                if(arr[mid]==i) 
                    flag=1;
                else if(arr[mid]>i) 
                    end=mid-1; 
                else 
                    start=mid+1;

            }
            if(flag==0)
            {
                ans.push_back(i); 
                count++;
            }
            i++;
        } 
        return ans[k-1];
    }
};

【问题讨论】:

  • 你为什么要找 Mid。你能解释一下逻辑吗?我觉得这太复杂了。由于给定的数组已经排序,因此与此相比,直接方法可能会更快。
  • 我正在使用二分法搜索元素 i
  • 您也可以发布问题链接。可能是编辑您的问题。我认为 TLE 是由于这种“logn”额外的复杂性,因为逻辑似乎很好
  • 最简单的解决方案将具有 O(n) 或 O(k) 的时间复杂度和 O(1) 的空间复杂度。方法是让 1 个for 循环从 1 变为 1000,并让 1 个counter 计算当前总缺失整数。一旦counterfor 循环中等于kfor 循环的索引i 就是答案。这种方法不需要二分查找逻辑。

标签: c++ arrays algorithm


【解决方案1】:

您的代码中至少有两个问题。

首先,对于导致无限循环的每个循环,flag 不会重置为 0

其次,当在数组中找到一个数字时,代码也会卡在while循环中,因为没有break语句。

这是一个有效的代码。我在循环中移动了flag 声明,并在向量中找到数字时添加了break 语句。

#include <iostream>
#include <vector>

using namespace std;


class Solution {
public:
    int findKthPositive(vector<int>& arr, int k) {
        vector<int> ans;
        int count=0,i=1;
        
        while(count<k)
        {
            int start=0,end=arr.size()-1,flag=0;
            while(start<=end)
            {
                int mid=start+(end-start)/2;
                if(arr[mid]==i) {
                    flag=1;
                    break;
                }
                else if(arr[mid]>i) 
                    end=mid-1; 
                else 
                    start=mid+1;

            }
            if(flag==0)
            {
                ans.push_back(i); 
                count++;
            }
            i++;
        } 
        return ans[k-1];
    }
};

int main() {

  std::cout << "Hello" << std::endl;
  Solution a;
  vector<int> testv = {2, 3, 4, 7, 11 };
  std::cout << a.findKthPositive(testv, 5) << std::endl;
}

【讨论】:

    【解决方案2】:

    您正在一次又一次地开始二分搜索。

    相反,您将计算 a[i]i 之间的差异,并将此差异与 k 进行比较 - 所以唯一的循环,对给定 k 的唯一二进制搜索是需要的,时间是对数的

    Python 中的代码,但我希望它是可以理解的:

    def findit(a, n, k):
        if a[0] > k:
            return k
        if k > a[n-1] - n:
            return k + a[n-1] - n-1
    
        #binary search of index of first occurrence of the least element   greater than key 
        start = 0
        end = n - 1
        while start <= end:
            mid = (start + end) // 2
            t = a[mid] - mid
            if t <= k:
                start = mid + 1
            else:
                idx = mid
                end = mid - 1
        return(k + idx)
    
    a = [2,3,4,7,11]
    for k in range(1, 9):
        print(findit(a, len(a), k))
    
    result    
    1   5   6   8   9   10   12   13
    

    【讨论】:

    • 为什么if k &gt; a[n-1] - n:的返回不只是k + n?
    • 返回 (k+idx) 的原因是什么?我知道 idx 是第一次出现大于 k 的元素的索引。但是有什么合乎逻辑的理由为什么我们会返回 (k+idx) 吗?
    • @Ishan Bhatt k 错过的项目 + 地点 idx 给予价值 k+idx
    【解决方案3】:

    你可以做一个桶,因为这些限制表明了这一点。

    vector<int> sorted_array;
    
    int bucket[1000];
    
    for (int i=0;i<1000;i++)
    {
      bucket[i] = 0;
    }
    
    for (auto elem : sorted_array)
    {
      bucket[elem]++;
    }
    
    int k = <user_input>;
    
    int result = -1;
    int index = 0;
    for (int i=0;i<1000;i++)
    {
      if (bucket[i] == 0) // missing
      {
        index++;
      }
      if (index == k)
      {
        result = i;
        break;
      }
    }
    
    if (result > 0)
    {
       cout << "We have a result: " << result << endl;
    }
    else
    {
       cout << "No result found\n";
    }
    

    【讨论】:

      【解决方案4】:

      正如我所怀疑的那样,二进制搜索在您的解决方案中增加了额外的时间和计算。你正在添加k x O(log n),直到你得到想要的答案。

      可以尝试更简单的方法,因为数组已经排序

        class Solution {
      public:
          int findKthPositive(vector<int>& arr, int k) {
              // you dont need an extra array to store the `k-1` numbers
      
              int count=0, i=0, curr_num = 1;
              
              while (i < arr.size()){
                  if (curr_num == arr[i]){
                  // we compare the numbers simply with current position if it is present in arr woo-hoo otherwise increase count
                      i++;
                  } else {
                      count++;
                      if (count == k){
                          break;
                      }
                      
                  }
                  curr_num++;
              }
      
              if (count < k){
                  while (count < k) {
                      count++;
                      if (count == k){
                          break;
                      }
                      curr_num++;
                  }
                  
              }
      
              return curr_num;
          }
      };
      };
      

      【讨论】:

        猜你喜欢
        • 2018-11-28
        • 1970-01-01
        • 2021-08-24
        • 2016-09-25
        • 2013-11-30
        • 1970-01-01
        • 2015-06-05
        • 2021-09-03
        • 1970-01-01
        相关资源
        最近更新 更多