我想找到给定列表中的最小缺失正整数。也就是说,如果给出一个正整数列表,即重复大于0,如何找到那些缺少最小的整数。
序列中始终至少有一个缺失的元素。
例如给定
std::vector<int> 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;
}
这是O(nmlogn)的时间,但我无法弄清楚是否有更高效的C ++ STL方法来做到这一点?
这不是一个练习,但我正在为自我提升做一系列问题,我发现这是一个非常有趣的问题。我很想知道如何改进这一点。
答案 0 :(得分:1)
您可以使用std::sort
,然后将std::adjacent_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;
}
}
当没有这样的元素存在时会发生什么,例如当向量为空时。
答案 1 :(得分:0)
您可以使用算法将标准模板库c ++用于您的代码。
#include <algorithm> // std::sort
算法中的std::sort
:
std::vector<int> v={9,2,5,1,3};
std::sort(v.begin(),v.end());
std::cout << v[0];
我希望我明白你的意思。
答案 2 :(得分:0)
找到第一个缺失的阳性,有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;
}
};
答案 3 :(得分:0)
假设数据先排序:
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;});
答案 4 :(得分:-1)
你可以通过构建一组整数并在集合中添加更大的整数来实现这一点,并保持最小值不作为计数器。一旦有一个等于后者的数字,请通过set删除元素,直到缺少整数。
请参阅下面的实施。
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;
}
如果你的序列在一个向量中,你应该使用它:
solver(sequence.begin(),sequence.end());
该算法在时间上是O(N),在空间中是O(1),因为它只使用计数器,恒定大小的附加空间和一些迭代器来跟踪最小值。
复杂性(增长率的顺序)该算法仅保留输入的子集,该输入预期相对于输入的增长率具有恒定的增长顺序,因此在空间中为O(1)。迭代的增长率是O(N + NlogK),其中K是所见较大数字的较大子序列的增长率。后者是上述恒定增长率的子序列,即K = 1,这导致算法具有O(N)复杂度。(见注释)