如何找到无需移除最大元素,并再次搜索上述? 有没有更有效的方式来做到这一点? 如果这些元素是重复不要紧。
Answer 1:
for (e: all elements) {
if (e > largest) {
second = largest;
largest = e;
} else if (e > second) {
second = e;
}
}
你既可以初始化largest
和second
,以适当的下界,或在列表中的前两个项目(检查哪一个更大,并且不要忘记检查,如果列表中有至少两项产品)
Answer 2:
使用partial_sort ?
std::partial_sort(aTest.begin(), aTest.begin() + 2, aTest.end(), Functor);
一个例子:
std::vector<int> aTest;
aTest.push_back(3);
aTest.push_back(2);
aTest.push_back(4);
aTest.push_back(1);
std::partial_sort(aTest.begin(), aTest.begin()+2,aTest.end(), std::greater<int>());
int Max = aTest[0];
int SecMax = aTest[1];
Answer 3:
nth_element(begin, begin+n,end,Compare)
的地方,这将是第n个元素(其中,“第一”是“零”)如果范围[begin, end)
的位置进行分选, begin+n
,并确保一切从[begin,begin+n)
在排序列表中的第n个元素之前将会出现。 所以,你想要的代码是:
nth_element(container.begin(),
container.begin()+1,
container.end(),
appropriateCompare);
这将在你的情况下工作得很好,因为你只想找两个最大。 假设你appropriateCompare排序的东西从最大到最小,与第二大要素是在位置1和最大的将是在位置0。
Answer 4:
让我们假设你的意思是在列表中找到最大的两个独特的价值观。
如果列表已经排序,那么就看看倒数第二个元素(或者说,从最终寻找的倒数第二个值重复)。
如果列表未排序,那就不必对它进行排序。 排序充其量为O(n LG N)。 简单的线性迭代是O(n),所以刚超过跟踪元件循环:
v::value_type second_best = 0, best = 0;
for(v::const_iterator i=v.begin(); i!=v.end(); ++i)
if(*i > best) {
second_best = best;
best = *i;
} else if(*i > second_best) {
second_best = *i;
}
当然还有其他的标准,而这些可以全部投入到循环内的测试。 然而,你应该是指两个元素都具有相同的最大价值应该发现,你必须要考虑发生了什么应该3个以上元素都有这个最大的价值,或者如果两个或多个元素具有第二位。
Answer 5:
最佳算法不应该需要超过1.5 * N - 2的比较。 (一旦我们决定,它是为O(n),什么是在N前面的系数?2 * N比较比最佳少)。
所以,首先要确定的“赢家”,并在每对中的“失败者” - 这是0.5 * N的比较。
然后通过比较确定获奖者最大的元素 - 这是另一个0.5 * N - 1个比较。
然后通过比较对输确定第二大元件,其中最大的元件从相对于所有其他对优胜者来到 - 另一个0.5 * N - 1个比较。
总比较= 1.5 N - 2。
Answer 6:
答案取决于如果你只想值,或也可以在值指向迭代器。
@will答案的小的修改。
v::value_type second_best = 0, best = 0;
for(v::const_iterator i=v.begin(); i!=v.end(); ++i)
{
if(*i > best)
{
second_best = best;
best = *i;
}
else if (*i > second_best)
{
second_best = *i;
}
}
Answer 7:
从n..m创建一个子列表,排序,上去下来。 然后抓住前两个元素。 删除从原单列表中的这些元素。
Answer 8:
您可以扫描列表中的道次和保存第一和第二值,具有O(n)的效率,同时排序是O(n log n)的。
编辑:
我认为这部分排序是O(N日志K)
Answer 9:
未经测试,但有趣:
template <typename T, int n>
class top_n_functor : public unary_function<T, void>
{
void operator() (const T& x) {
auto f = lower_bound(values_.begin(), values_.end(), x);
if(values_.size() < n) {
values_.insert(f, x);
return;
}
if(values_.begin() == f)
return;
auto removed = values_.begin();
values_.splice(removed, values_, removed+1, f);
*removed = x;
}
std::list<T> values() {
return values_;
}
private:
std::list<T> values_;
};
int main()
{
int A[] = {1, 4, 2, 8, 5, 7};
const int N = sizeof(A) / sizeof(int);
auto vals = for_each(A, A + N, top_n_functor<int,2>()).values();
cout << "The top is " << vals.front()
<< " with second place being " << *(vals.begin()+1) << endl;
}
Answer 10:
如果最大的是第一个元素,在[最大+ 1,结束)搜索第二最大。 在[开始,最大的),否则搜索和[最大+ 1,结束),并采取最大的两个。 当然,这有O(2N),所以它不是最优的。
如果您有随机访问迭代器,你可以做的是快速排序并和使用不断优雅递归:
template< typename T >
std::pair<T,T> find_two_largest(const std::pair<T,T>& lhs, const std::pair<T,T>& rhs)
{
// implementation finding the two largest of the four values left as an exercise :)
}
template< typename RAIter >
std::pair< typename std::iterator_traits<RAIter>::value_type
, typename std::iterator_traits<RAIter>::value_type >
find_two_largest(RAIter begin, RAIter end)
{
const ptr_diff_t diff = end-begin;
if( diff < 2 )
return std::make_pair(*begin, *begin);
if( diff < 3 )
return std::make_pair(*begin, *begin+1);
const RAIter middle = begin + (diff)/2;
typedef std::pair< typename std::iterator_traits<RAIter>::value_type
, typename std::iterator_traits<RAIter>::value_type >
result_t;
const result_t left = find_two_largest(begin,middle);
const result_t right = find_two_largest(middle,end);
return find_two_largest(left,right);
}
这有O(n)和不应该超过比较学校名称的实现 。
Answer 11:
前k通常是有点大于n更好(日志k)的
template <class t,class ordering>
class TopK {
public:
typedef std::multiset<t,ordering,special_allocator> BEST_t;
BEST_t best;
const size_t K;
TopK(const size_t k)
: K(k){
}
const BEST_t& insert(const t& item){
if(best.size()<k){
best.insert(item);
return best;
}
//k items in multiset now
//and here is why its better - because if the distribution is random then
//this and comparison above are usually the comparisons that is done;
if(compare(*best.begin(),item){//item better than worst
erase(begin());//the worst
best.insert(item); //log k-1 average as only k-1 items in best
}
return best;
}
template <class it>
const BEST_t& insert(it i,const it last){
for(;i!=last;++i){
insert(*i);
}
return best;
}
};
当然, special_allocator
可以在本质上只是ķ多集value_types的数组,(这些节点的列表通常上有没有像其他k为在多集使用,直到它的时间投入在一个新的,我们抹去然后立即LY重复使用。很高兴有这样或其他内存分配/免费的std :: multiset的和高速缓存行废话杀死你。它是一种(非常)工作的点点给它静止状态而不违反STL分配规则。
不如整整2的专用算法中,但固定k<<n
,我猜(2N +增量* n),其中三角洲是小-我DEK ACP VOL3 S&S的打包带走,并在三角洲的估计是有点多我想要做的工作。
平均最差是我Ñ猜(日志(K-1)+ 2)中相反的顺序和所有不同时。
最好为2n + K(日志k)的最佳是第一第k