【问题标题】:given an array A of N integers, returns the smallest positive integer (greater than 0) that does not occur in A给定一个包含 N 个整数的数组 A,返回 A 中未出现的最小正整数(大于 0)
【发布时间】:2021-04-21 14:16:21
【问题描述】:

我试图解决这个练习 我得到了 66% 我不明白为什么 你能帮忙吗?


练习是: 写一个函数:

int 解(向量 &A);

给定一个包含 N 个整数的数组 A,返回在 A 中没有出现的最小正整数(大于 0)。

例如,给定 A = [1, 3, 6, 4, 1, 2],函数应该返回 5。

给定 A = [1, 2, 3],函数应该返回 4。

给定 A = [−1, −3],函数应该返回 1。 我写的解决方案是:

#include <algorithm>
#include<cmath>
using namespace std;

int solution(vector<int> &A) {
    if (A.size() == 0 || (A.size() == 1 && A.at(0) <= 0))
        return 1;
    if (A.size() == 1)
        return A.at(0) + 1;

    sort(A.begin(), A.end());
    if (A.at(A.size() - 1) <= 0)
        return 1;

    auto ip = std::unique(A.begin(), A.end());
    A.resize(distance(A.begin(), ip));
    A.erase(remove_if(A.begin(), A.end(), [](const int i) { return i < 0; }),A.end());
    if (A.at(0) != 1)
        return 1;
    if (A.size() == 1)
        return (A.at(0) != 1 ? 1 : 2);
    int i = 0;
    for (; i < A.size(); ++i) {
        if (A.at(i) != i + 1)
            return A.at(i - 1) + 1;
    }
    return A.at(A.size()) + 1;
}

【问题讨论】:

  • 逻辑大致在这里,你必须调试才能解决问题。编写单元测试和/或尝试查找产生错误输出的输入。
  • 仅供参考 std::sortadjacent_find 将其设为 trivial and much shorter solution,无需调整大小、擦除、删除等。

标签: c++ arrays vector


【解决方案1】:

这是错误的

if(A.size()==1)  
return A.at(0)+1;

如果A{2},则当正确答案为 1 时,该代码将返回 3

还有

A.erase(remove_if(A.begin(), A.end(),[](const int i) {return i < 0; }),A.end());

应该是

A.erase(remove_if(A.begin(), A.end(),[](const int i) {return i <= 0; }),A.end());

还有

return A.at(A.size()) + 1;

是保证向量越界错误。

即使是少量的测试和调试也会发现这些错误。这是你应该养成的习惯。

我认为代码中的特殊情况太多了,只会使代码复杂化并增加错误的机会。

【讨论】:

    【解决方案2】:

    其他人已经指出了主要错误是什么,但我想邀请您尝试不同的解决方案,而不是尝试修复所有错误并花费大量时间进行调试,因为您的解决方案似乎有点过于复杂。

    在这里我提出一种你可以思考问题的方法:

    • 函数可以返回的最小数字是多少?由于它返回一个正整数,所以它是 1,在这种情况下 1 不在数组中。既然我们可以使用任何数字
    • 如果数组中没有一个,我如何找到想要的数字?你的直觉是正确的,如果你的向量是排序的,那就更容易了:你可以迭代你的数据,当你在两个后续元素之间找到一个“洞”时,洞的第一个元素的值+1就是你的结果
    • 如果数组包含1并且没有孔怎么办?好吧,您返回不在数组中的最小元素,因此最后一个元素 + 1。您可能会注意到,通过检查您的“候选”值是否(这是一个不应该返回的数字,所以

    让我们进入代码:

    int solution(std::vector<int>& v){
        int retVal=0;
        std::sort(v.begin(), v.end());
        for(int i=0; i<v.size()-1; i++){
            if(v[i]>0 && v[i+1]>v[i]+1){
                retVal=v[i]+1;
                break;
            }
        }
        if(retVal==0) {
            if (v.back() > 0)
                retVal = v.back() + 1;
            else
                retVal = 1;
        }
        return retVal;
    }
    

    按照建议,您可以更多地使用标准库,但我认为这相当简单和高效。

    其他说明: 我认为你的任务不会打扰你,但我只是为了完整性而提到。大多数情况下,您不希望函数修改参数:您可以“按值”传递向量,这意味着实际上您传递了数据的完整副本,而不触及原始副本,或者您可以传递 const 引用并在函数内部创建一个副本。

    【讨论】:

    • 对不起,我看错了作业,我之前的解决方案是错误的。我编辑了答案,所以现在可以@Roth-Tla-1
    【解决方案3】:

    以下算法的复杂度为 O(n)。无需排序或擦除。

    如果n是数组大小,我们知道第一个缺失值小于或等于n+1

    然后我们只需要使用一个大小为 n+2 的数组,present[n+2],初始化为 0,然后查看所有值 A[i]

    if (A[i] <= 1+n && A[i] > 0) present[A[i]] = 1;
    

    最后,在第二步中,我们只需检查数组present[.],并搜索第一个索引k 使得present[k]==0.

    #include <iostream>
    #include <vector>
    
    int find_missing (const std::vector<int> &A) {
        int n = A.size();
        std::vector<int> present (n+2, 0);
        int vmax = n+1;
        for (int i = 0; i < n; ++i) {
            if (A[i] <= vmax && A[i] > 0) {
                present[A[i]] = 1;
            }
        }
        for (int k = 1; k <= vmax; ++k) {
            if (present[k] == 0) return k;
        }
        return -1;
    }
    
    int main() {
        std::vector<int> A = {1, 2, 0, 3, -3, 5, 6, 8};
        
        int missing = find_missing (A);
        std::cout << "First missing element = " << missing << std::endl;
        return 0;
    }
    

    【讨论】:

      【解决方案4】:

      这个答案是 PaulMcKenzie 在评论中给出的建议的实施。

      所以,所有功劳归于 PaulMcKenzie

      这不是最快的解决方案,但很紧凑。这个想法基本上是。

      • 对数据进行排序
      • 然后比较相邻的值,如果下一个值等于上一个值+1。

      如果没有,那么我们发现了一个差距。这可以通过使用函数std::adjacent_find 来实现。描述可以在here找到。

      我们将所有附带条件放入 lambda。如果std::adjacent_find 找不到值,那么我们取下一个可能的正值。

      我不确定,我可以描述更多。请看下面的例子:

      #include <iostream>
      #include <vector>
      #include <algorithm>
      
      int solution(std::vector<int>& data) {
      
          // Sort
          std::sort(data.begin(), data.end());
      
          // Check if there is a gap in the positive values
          const auto gap = std::adjacent_find(data.begin(), data.end(), [](const int p, const int n) { return (n !=p) && (n != (p + 1) && p>0); });
      
          // If there is no gap, the take the next positive value
          return (gap == data.end()) ?  (data.back() > 0 ? data.back() + 1 : 1) : *gap + 1;
      }
      
      int main() {
          //Some test cases
          std::vector<std::vector<int>> testCases{
              {1,3,6,4,1,2},
              {1,2,3},
              {-1,-3}
          };
          for (auto& testCase : testCases)
              std::cout << solution(testCase) << '\n';
          
          return 0;
      }
      

      【讨论】:

        猜你喜欢
        • 2018-08-19
        • 2022-11-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-07-25
        • 1970-01-01
        • 2017-04-15
        相关资源
        最近更新 更多