¿Cómo puedo encontrar lo anterior sin quitar el elemento más grande y buscar de nuevo? ¿Hay una manera más eficiente de hacer esto? No importa si estos elementos son duplicados.Encuentra el elemento más grande y el segundo más grande en un rango
Respuesta
for (e: all elements) {
if (e > largest) {
second = largest;
largest = e;
} else if (e > second) {
second = e;
}
}
Usted podría inicializar y largest
second
a una cota inferior adecuada, o para los dos primeros elementos de la lista (comprobar cuál es el más grande, y no se olvide de comprobar si la lista tiene al menos dos elementos)
Cree una sublista de n..m, oriéntela descendiendo. Luego toma los primeros dos elementos. Eliminar estos elementos de la lista original.
usando partial_sort?
std::partial_sort(aTest.begin(), aTest.begin() + 2, aTest.end(), Functor);
Un ejemplo:
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];
1 Yo no sabía nada de partial_sort. PERO no funciona si quiere mantener el orden de la lista original. –
Puede usar partial_sort_copy para ese –
¿no le conseguirá esto los elementos más pequeños? Es fácil de arreglar usando un operador de comparación diferente. +1 – rmeador
Asumamos que quiere decir para encontrar los dos valores únicos más grandes de la lista.
Si la lista ya está ordenada, simplemente mire el segundo último elemento (o más bien, itere desde el final buscando el segundo último valor).
Si la lista no está ordenada, no se moleste en ordenarla. La clasificación es en el mejor de los casos O (n lg n). iteración lineal simple es O (n), por lo que sólo un bucle sobre los elementos de mantenimiento de pista:
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;
}
Por supuesto, hay otros criterios, y estos podrían todos ser puesto en la prueba dentro del bucle. Sin embargo, si quiere decir que deben encontrarse dos elementos que tienen el mismo valor más grande, debe considerar qué sucede si tres o más elementos tienen el mayor valor o si dos o más elementos tienen el segundo valor más grande.
Puede escanear la lista de una pasada y guardar los valores 1º y 2º, que tienen una eficacia O (n) mientras la ordenación es O (n log n).
EDIT:
creo que ese tipo parcial es O (n log k)
La respuesta depende de si sólo desea que los valores, o también iteradores que señalan en los valores.
Modificación menor de la respuesta @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;
}
}
nth_element (comienza, comienzan + n, final, de comparación) coloca el elemento que sería n (donde "primero" es "0 ª") si el rango [begin, end) se clasificaron en la posición comienzan + ny se asegura de que todo desde [begin, begin + n) aparezca antes del enésimo elemento en la lista ordenada. Entonces el código que desea es:
nth_element(container.begin(),
container.begin()+1,
container.end(),
appropriateCompare);
Esto funcionará bien en su caso, ya que solo está buscando las dos más grandes. Suponiendo que su apropiadoCompare ordena las cosas de mayor a menor, el segundo elemento más grande estará en la posición 1 y el más grande estará en la posición 0.
+1, nth_element tiene mejor tiempo de ejecución que partial_sort – Naveen
El algoritmo óptimo no debería necesitar más de 1.5 * N - 2 comparaciones. (Una vez que hemos decidido que es O (n), ¿cuál es el coeficiente frente a las comparaciones N? 2 * N es menos que óptimo).
Por lo tanto, primero determine el "ganador" y el "perdedor" en cada par - eso es 0.5 * N comparaciones.
A continuación, determine el elemento más grande comparando los ganadores, es decir, otras 0.5 * N - 1 comparaciones.
Luego determine el segundo elemento más grande comparando el perdedor del par de donde vino el elemento más grande contra los ganadores de todos los otros pares: otras 0.5 * N - 1 comparaciones.
totales comparaciones = 1,5 N - 2.
No comprobado pero divertido:
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;
}
Si el más grande es el primer elemento, la búsqueda de la segunda más grande de [más grande + 1, final). De lo contrario, busque en [begin, largest) y [largest + 1, end] y tome el máximo de los dos. Por supuesto, esto tiene O (2n), por lo que no es óptimo.
Si tiene iteradores de acceso aleatorio, se puede hacer como una especie rápida y no utilizar la siempre elegante recursividad:
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);
}
Esto tiene O (n) y no debe hacer más comparaciones de NomeN's implementation.
k superior es generalmente un poco mejor que n (k log)
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;
}
};
Por supuesto, el special_allocator
puede en esencia ser sólo un conjunto de value_types multiconjuntos k y una lista de los nodos (que normalmente no tiene nada en él ya que los otros k están en uso en el multiset hasta que sea hora de poner uno nuevo y borrarlo y luego reutilizarlo inmediatamente. Es bueno tener esto o la memoria alloc/free en std :: multiset y el caché la mierda de línea te mata. Es un (muy) pequeño trabajo para darle un estado estático sin violar las reglas de asignación de STL.
No es tan bueno como un specializ ed algo para exactamente 2 pero para k<<n
fijo, GUESS (2n + delta * n) donde delta es pequeño - mi DEK ACP vol3 S & S está empaquetado y una estimación en delta es un poco más de trabajo que quiero hacer .
el peor promedio es Supongo que n (log (k-1) + 2) cuando está en el orden opuesto y todo distinto.
mejor es 2n + k (k log) para la mejor k ser la primera
- 1. encuentra el algoritmo de submatriz más grande
- 2. Encuentra el más grande de tres valores en PHP
- 3. Fortran: el número entero más grande y el más pequeño
- 4. Seleccione el segundo más grande de una tabla sin límite
- 5. Puzzle: Encuentra el rectángulo más grande (problema de rectángulo máximo)
- 6. consulta para encontrar el primer y el segundo valor más grande de un grupo
- 7. Imagen más grande para el primer elemento de gridview android
- 8. Encuentra el valor más grande más pequeño que x en una matriz ordenada
- 9. ¿Cuál es la consulta SQL más simple para encontrar el segundo valor más grande?
- 10. Obtener el tipo más grande disponible
- 11. Número más grande y más pequeño en una matriz
- 12. DialogBoxIndirect crea un diálogo más grande que
- 13. Encontrar el valor más grande en un diccionario
- 14. PHP Constante posible más grande
- 15. Columna no nula más grande
- 16. object_setClass a clase más grande
- 17. ¿Cómo funciona el módulo de un dividendo más pequeño y un divisor más grande?
- 18. Jquery encuentra el elemento coincidente más cercano
- 19. Para hallar más grande elemento más pequeño que K en un BST
- 20. Encuentra el 10% más grande de los números en una matriz en orden
- 21. Encuentra el número de ángulos internos de un polígono, más grande que 180º
- 22. ¿Cómo puedo alinear columnas donde el número más grande o la cadena más grande es el indicador de alineación?
- 23. ¿Qué es más grande que un doble?
- 24. ¿Cómo elimino el elemento más pequeño y más grande de una matriz de una manera adecuada para C++?
- 25. ¿Cómo encontrar el número más pequeño y más grande en una matriz?
- 26. Dividir el repositorio grande de Git en muchos más pequeños
- 27. ¿Utiliza AWK para encontrar el número más pequeño y más grande en una columna?
- 28. Encontrar el palíndromo más grande en la implementación de cadenas
- 29. ¿Cuál es la función integrada que encuentra el número primo siguiente más grande en Java?
- 30. Python - Encuentra el número más grande en una lista de números
Simple de codificar ... ¿qué más puede pedir? Es cierto que hacer una búsqueda es menos "complejo", pero casi seguro será más lento debido a la diversión de acceso a la memoria. – Goz
la ordenación es por definición más lenta, porque debe inspeccionar los elementos al menos O (n log n) veces. Esto garantiza que solo se inspeccionan los elementos O (n) veces (donde n es #elementos, por supuesto). Solo si la operación se repite en la misma lista, la ordenación se vuelve más eficiente. – NomeN
Esto es lo que terminé implementando (probablemente debería haber mencionado eso en el OP) pero estaba buscando algo diferente (y posiblemente más rápido). – Jacob