C++ 如何用STL方法查找列表中的最小缺失整数

C++ 如何用STL方法查找列表中的最小缺失整数,c++,algorithm,stl,C++,Algorithm,Stl,我想找到给定列表中缺失的最小正整数。也就是说,如果给定一个正整数列表,即大于0且有重复,如何从缺少的整数中找到最小的整数 序列中始终至少缺少一个元素 举个例子 std::vector<int> S={9,2,1,10}; std::vector S={9,2,1,10}; 答案应该是3,因为缺少的整数是3,4,5,6,7,8,11,。。。最小值是3 我想到了这个: int min_missing( std::vector<int> & S) { int m

我想找到给定列表中缺失的最小正整数。也就是说,如果给定一个正整数列表,即大于0且有重复,如何从缺少的整数中找到最小的整数

序列中始终至少缺少一个元素

举个例子

std::vector<int> S={9,2,1,10};
std::vector S={9,2,1,10};
答案应该是3,因为缺少的整数是3,4,5,6,7,8,11,。。。最小值是3

我想到了这个:

int min_missing( std::vector<int> & S)
{
  int max = std::max_element(S.begin(), S.end());
  int min = std::min_element(S.begin(), S.end());
  int i = min;
  for(; i!=max and std::find(S.begin(), S.end(), i) != S.end() ; ++i);
  return i;
}
int min_缺失(std::vector&S)
{
int max=std::max_元素(S.begin(),S.end());
int min=std::min_元素(S.begin(),S.end());
int i=最小值;
对于(;i!=max和std::find(S.begin(),S.end(),i)!=S.end();++i);
返回i;
}

这是O(nMLogn),但我不能确定是否有一种更有效的C++ STL方式来做这个?


这不是一个练习,但我正在做一系列的自我提高问题,我发现这是一个非常有趣的问题。我很想看看如何改进这一点。

您可以通过构建一组整数并在集合中添加较大的整数,并将集合中未显示的最小值作为计数器来实现这一点。一旦有一个数等于后一个数,就通过集合删除元素,直到缺少一个整数

请参见下面的实施

template<typename I> typename I::value_type solver(I b, I e)
{
    constexpr typename I::value_type maxseen=
      std::numeric_limits<typename I::value_type>::max();
    std::set<typename I::value_type> seen{maxseen};

    typename I::value_type minnotseen(1);

    for(I p=b; p!=e;++p)
    {
        if(*p == minnotseen)
        {
            while(++minnotseen == *seen.begin())
            {
                seen.erase(seen.begin());
            }

        } else if( *p > minnotseen)
        {
            seen.insert(*p);
        }
    }

    return minnotseen;
}
该算法在时间上是O(N),在空间上是O(1),因为它只使用一个计数器、恒定大小的额外空间和几个迭代器来跟踪最小值


复杂度(增长率阶数)该算法仅保留输入的一个子集,该子集相对于输入的增长率具有恒定的增长阶数,因此在空间中为O(1)。迭代的增长率是O(N+NlogK),其中K是看到的较大数的较大子序列的增长率。后者是上述恒定增长率的子序列,即K=1,这导致算法具有O(N)复杂度。(请参阅注释)

您可以使用标准模板库c++来处理代码

#include <algorithm>    // std::sort

我希望我能理解你在看什么。

用O(n)时间和恒定空间找到第一个缺失的正数

基本上,当您读取一个值a时,只需和S[a]交换,就像2应该和a[2]交换一样

class Solution {
public:
/**    
 * @param A: a vector of integers
 * @return: an integer
 */
int firstMissingPositive(vector<int> A) {
    // write your code here
    int n = A.size();
    for(int i=0;i<n;)
    {
        if(A[i]==i+1)
            i++;
        else
        {
            if(A[i]>=1&&A[i]<=n&& A[A[i]-1]!=A[i])
                swap(A[i],A[A[i]-1]);
            else
                i++;
        }
    }
    for(int i=0;i<n;i++)
        if(A[i]!=i+1)
            return i+1;
    return n+1;
   }
};
类解决方案{
公众:
/**    
*@param A:整数向量
*@return:整数
*/
int firstMissingPositive(向量A){
//在这里编写代码
int n=A.size();

对于(int i=0;i=1&&A[i],假设首先对数据进行排序:

    auto missing_data = std::mismatch(S.cbegin(), S.cend()-1, S.cbegin() + 1,
                                      [](int x, int y) { return (x+1) == y;});
编辑 由于未对输入数据进行排序,最简单的解决方案是首先对其进行排序:

   std::vector<int> data(S.size());
   std::partial_sort_copy (S.cbegin(), S.cend(), data.begin(), data.end());
   auto missing_data = std::mismatch (data.cbegin(), data.cend()-1, data.cbegin()+1,
                                      [](int x, int y) { return (x+1) == y;});
std::向量数据(S.size());
std::部分排序拷贝(S.cbegin(),S.cend(),data.begin(),data.end());
自动缺少_data=std::不匹配(data.cbegin(),data.cend()-1,data.cbegin()+1,
[](int x,int y){返回(x+1)=y;};

您可以使用
std::sort
,然后使用带有自定义谓词的
std::nexting\u find

int f(std::vector<int>  v)
{
    std::sort(v.begin(), v.end());
    auto i = std::adjacent_find( v.begin(), v.end(), [](int x, int y) 
    {
        return y != x+1;
    } );

    if (i != v.end())
    {
         return *i + 1;
    }
}
intf(标准::向量v)
{
排序(v.begin(),v.end());
自动i=std::相邻查找(v.begin(),v.end(),[](int x,int y)
{
返回y!=x+1;
} );
如果(i!=v.end())
{
返回*i+1;
}
}

当不存在这样的元素时,例如向量为空时,会发生什么情况,这是没有答案的。

你能举个例子吗?我不确定我是否理解你的意思。这是什么意思?当你说“有效”时,你的意思是节省时间、节省空间还是节省程序员的工作时间?@ChristianHackl,除非另有规定,否则通常暗示节省时间。在这种情况下,通常不考虑程序员的工作时间。这是一个序列{1,2,…}这意味着它是有序的?你的解决方案的复杂性是什么?@jjknuth O(n log n):std::sort以O(n log n)为主,std::nexture_find是线性的。这个算法实际上在时间上是O(n log n),在空间上是O(n)(你忘了你的
std::set
)@ruakh这个集合只保留了n大小输入的一个子集(较大的数字),因此在时间上是O(n+nlogk),在空间上是O(logk)。我假设k(较大子序列的大小)相对较小,这平均应该是预期的,因为在无限序列中具有无限长的重复子序列的数量不应假设为无限(其增长率较小).正如你所看到的,分析有点复杂。不过为了让你放心,我已经测试过了。@ruakh(n中的某个)/n!-->0与n->inf一样以超指数速度增长。这就解决了这个问题。无论如何,感谢没有任何原因的下一票。@ruakh,输入大小不仅仅是唯一的数字,因为OP没有指定,因此对于输入大小(n)和输入大小n,有无限大小的重复。例如,{1,1,1,4,4,5,5,1,1,1}最小值不可见2,关联集的基数为4,输入大小为10。因此,当n->inf最坏的情况是O(n)和O(1)。@ruakh我认为这是哈希映射等的情况,声明的绑定摊销成本是恒定的。有一种情况下,您总是得到它的O(n)。在这里不会发生这种情况,因为随着(输入大小)的增加,倍数最终将超过(内部存储大小)/(输入大小)比率。这只返回当前数字中的最小值。问题是那些不存在的数字。
   std::vector<int> data(S.size());
   std::partial_sort_copy (S.cbegin(), S.cend(), data.begin(), data.end());
   auto missing_data = std::mismatch (data.cbegin(), data.cend()-1, data.cbegin()+1,
                                      [](int x, int y) { return (x+1) == y;});
int f(std::vector<int>  v)
{
    std::sort(v.begin(), v.end());
    auto i = std::adjacent_find( v.begin(), v.end(), [](int x, int y) 
    {
        return y != x+1;
    } );

    if (i != v.end())
    {
         return *i + 1;
    }
}