在查找范围最大和第二大元素(Find largest and second largest elem

2019-07-17 18:24发布

如何找到无需移除最大元素,并再次搜索上述? 有没有更有效的方式来做到这一点? 如果这些元素是重复不要紧。

Answer 1:

for (e: all elements) {
 if (e > largest) {
   second = largest;
   largest = e;
 } else if (e > second) {
   second = e;
 }
}

你既可以初始化largestsecond ,以适当的下界,或在列表中的前两个项目(检查哪一个更大,并且不要忘记检查,如果列表中有至少两项产品)



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



文章来源: Find largest and second largest element in a range