C # encuentra el valor y el índice de matriz más altos
92
Entonces, tengo una matriz numérica sin clasificar int[] anArray = { 1, 5, 2, 7 };y necesito obtener tanto el valor como el índice del valor más grande en la matriz, que sería 7 y 3, ¿cómo haría esto?
Hasta ahora, he intentado usar el método Max () y luego usar el método de búsqueda binaria para obtener el índice de ese valor máximo, pero esto no funciona a menos que la matriz esté ordenada, por lo que no puedo usarla, cuando intenté que me dio números negativos
Edmund Rojas
@EdmundRojas No es necesario utilizar la búsqueda binaria. Una búsqueda lineal simple funciona bien para listas sin clasificar.
millimoose
Respuestas:
144
Esta no es la forma más glamorosa, pero funciona.
(debe tener using System.Linq;)
int maxValue = anArray.Max();
int maxIndex = anArray.ToList().IndexOf(maxValue);
Ahorras mucho tiempo de codificación, pero terminarás revisando la colección dos veces.
Garo Yeriazarian
11
Ni siquiera necesita la .ToList()implementación explícita de matricesIList
millimoose
@GaroYeriazarian Si la complejidad lineal es demasiado para su caso de uso, probablemente necesite recortar algo más que reducir el factor constante en un tercio. (Aunque obviamente no es una optimización insignificante).
millimoose
1
@ sa_ddam213 Las matrices implementan la IListinterfaz, pero lo hacen explícitamente: msdn.microsoft.com/en-us/library/… . (Las matrices también implementan la IList<T>interfaz genérica correspondiente .)
millimoose
1
@ sa_ddam213 No, el contrato de ToList()es copiar siempre. Sería una idea terrible que el método a veces se copiara y otras no; esto daría lugar a errores de alias bastante locos. De hecho, la implementación de ToList()es más o menosreturn new List(source)
Si el índice no está ordenado, debe recorrer la matriz al menos una vez para encontrar el valor más alto. Usaría un forbucle simple :
int? maxVal = null; //nullable so this works even if you have all super-low negativesint index = -1;
for (int i = 0; i < anArray.Length; i++)
{
int thisNum = anArray[i];
if (!maxVal.HasValue || thisNum > maxVal.Value)
{
maxVal = thisNum;
index = i;
}
}
Esto es más detallado que algo que usa LINQ u otras soluciones unifilares, pero probablemente sea un poco más rápido. Realmente no hay forma de hacer esto más rápido que O (N).
Puede guardar una iteración inicializando maxValcon el valor de la matriz en el índice 0 (asumiendo que la matriz tiene al menos una longitud de 1), indexen 0 y comenzando el ciclo for en i = 1.
Jon Schneider
14
El LINQ one [1] -liner obligatorio:
var max = anArray.Select((value, index) => new {value, index})
.OrderByDescending(vi => vi.value)
.First();
(La clasificación es probablemente un impacto en el rendimiento sobre las otras soluciones).
Solo agregar esta solución es la complejidad O (nlogn) en el mejor de los casos. Encontrar max se puede obtener en O (n) tiempo para una matriz sin clasificar.
dopplesoldner
13
Un breve resumen:
var max = anArray.Select((n, i) => (Number: n, Index: i)).Max();
Caso de prueba:
var anArray = newint[] { 1, 5, 2, 7 };
var max = anArray.Select((n, i) => (Number: n, Index: i)).Max();
Console.WriteLine($"Maximum number = {max.Number}, on index {max.Index}.");
// Maximum number = 7, on index 4.
caracteristicas:
Utiliza Linq (no tan optimizado como vainilla, pero la compensación es menos código).
No necesita ordenar.
Complejidad computacional: O (n).
Complejidad espacial: O (n).
Observaciones:
Asegúrese de que el número (y no el índice) sea el primer elemento de la tupla porque la clasificación de la tupla se realiza comparando elementos de tupla de izquierda a derecha.
Cabe señalar que para que esto funcione, el elemento que se maximiza debe ser el primero
Caius Jard
¿Qué quieres decir con @CaiusJard? Como se muestra en el caso de prueba, el elemento máximo se encontró correctamente y era el último.
Lesair Valmont
Primero en la Tupla, por ejemplo, anArray.Select((n, i) => ( Index: i, Number: n)).Max()encuentra el índice máximo en lugar del número máximo debido a la forma en que se comparan las tuplas (el elemento 1 es el más significativo, etc.)
Caius Jard
Justo @CaiusJard, agregué un comentario para señalar eso. Gracias.
Lesair Valmont
3
Aquí hay dos enfoques. Es posible que desee agregar manejo para cuando la matriz esté vacía.
publicstaticvoidFindMax()
{
// Advantages: // * Functional approach// * Compact code// Cons: // * We are indexing into the array twice at each step// * The Range and IEnumerable add a bit of overhead// * Many people will find this code harder to understandint[] array = { 1, 5, 2, 7 };
int maxIndex = Enumerable.Range(0, array.Length).Aggregate((max, i) => array[max] > array[i] ? max : i);
int maxInt = array[maxIndex];
Console.WriteLine($"Maximum int {maxInt} is found at index {maxIndex}");
}
publicstaticvoidFindMax2()
{
// Advantages: // * Near-optimal performanceint[] array = { 1, 5, 2, 7 };
int maxIndex = -1;
int maxInt = Int32.MinValue;
// Modern C# compilers optimize the case where we put array.Length in the conditionfor (int i = 0; i < array.Length; i++)
{
intvalue = array[i];
if (value > maxInt)
{
maxInt = value;
maxIndex = i;
}
}
Console.WriteLine($"Maximum int {maxInt} is found at index {maxIndex}");
}
Con 100000000 ints en matriz, no es una gran diferencia, pero aún así ...
classProgram
{
staticvoidMain(string[] args)
{
int[] arr = newint[100000000];
Random randNum = new Random();
for (int i = 0; i < arr.Length; i++)
{
arr[i] = randNum.Next(-100000000, 100000000);
}
Stopwatch stopwatch1 = new Stopwatch();
Stopwatch stopwatch2 = new Stopwatch();
Stopwatch stopwatch3 = new Stopwatch();
stopwatch1.Start();
var max = GetMaxFullIterate(arr);
Debug.WriteLine( stopwatch1.Elapsed.ToString());
stopwatch2.Start();
var max2 = GetMaxPartialIterate(arr);
Debug.WriteLine( stopwatch2.Elapsed.ToString());
stopwatch3.Start();
var max3 = arr.Max();
Debug.WriteLine(stopwatch3.Elapsed.ToString());
}
privatestaticintGetMaxPartialIterate(int[] arr)
{
var max = arr[0];
var idx = 0;
for (int i = arr.Length / 2; i < arr.Length; i++)
{
if (arr[i] > max)
{
max = arr[i];
}
if (arr[idx] > max)
{
max = arr[idx];
}
idx++;
}
return max;
}
privatestaticintGetMaxFullIterate(int[] arr)
{
var max = arr[0];
for (int i = 0; i < arr.Length; i++)
{
if (arr[i] > max)
{
max = arr[i];
}
}
return max;
}
publicstaticclassArrayExtensions
{
publicstaticintMaxIndexOf<T>(this T[] input)
{
var max = input.Max();
int index = Array.IndexOf(input, max);
return index;
}
}
Esto funciona para todos los tipos de variables ...
var array = newint[]{1, 2, 4, 10, 0, 2};
var index = array.MaxIndexOf();
var array = newdouble[]{1.0, 2.0, 4.0, 10.0, 0.0, 2.0};
var index = array.MaxIndexOf();
Solo otra perspectiva usando DataTable. Declare a DataTablecon 2 columnas llamadasindex y val. Agregue una AutoIncrementopción y ambos valores AutoIncrementSeedy a la columna. Luego use un bucle e inserte cada elemento de la matriz en una fila. Luego, usando el método, seleccione la fila que tenga el valor máximo.AutoIncrementStep1indexforeachdatatableSelect
Código
int[] anArray = { 1, 5, 2, 7 };
DataTable dt = new DataTable();
dt.Columns.AddRange(new DataColumn[2] { new DataColumn("index"), new DataColumn("val")});
dt.Columns["index"].AutoIncrement = true;
dt.Columns["index"].AutoIncrementSeed = 1;
dt.Columns["index"].AutoIncrementStep = 1;
foreach(int i in anArray)
dt.Rows.Add(null, i);
DataRow[] dr = dt.Select("[val] = MAX([val])");
Console.WriteLine("Max Value = {0}, Index = {1}", dr[0][1], dr[0][0]);
Encuentra el número más grande y el más pequeño de la matriz:
int[] arr = newint[] {35,28,20,89,63,45,12};
int big = 0;
int little = 0;
for (int i = 0; i < arr.Length; i++)
{
Console.WriteLine(arr[i]);
if (arr[i] > arr[0])
{
big = arr[i];
}
else
{
little = arr[i];
}
}
Console.WriteLine("most big number inside of array is " + big);
Console.WriteLine("most little number inside of array is " + little);
Esta es una versión de C #. Se basa en la idea de ordenar la matriz.
publicintsolution(int[] A)
{
// write your code in C# 6.0 with .NET 4.5 (Mono)
Array.Sort(A);
var max = A.Max();
if(max < 0)
return1;
elsefor (int i = 1; i < max; i++)
{
if(!A.Contains(i)) {
return i;
}
}
return max + 1;
}
///<summary>/// Returns max value///</summary>///<param name="arr">array to search in</param>///<param name="index">index of the max value</param>///<returns>max value</returns>publicstaticintMaxAt(int[] arr, outint index)
{
index = -1;
int max = Int32.MinValue;
for (int i = 0; i < arr.Length; i++)
{
if (arr[i] > max)
{
max = arr[i];
index = i;
}
}
return max;
}
Uso:
int m, at;
m = MaxAt(newint[]{1,2,7,3,4,5,6}, out at);
Console.WriteLine("Max: {0}, found at: {1}", m, at);
Esto se puede hacer con un forbucle sin cuerpo , si nos dirigimos hacia el golf;)
//a is the arrayint mi = a.Length - 1;
for (int i=-1; ++i<a.Length-1; mi=a[mi]<a[i]?i:mi) ;
El cheque de ++i<a.Length-1omite chequeando el último índice. No nos importa esto si lo configuramos como si el índice máximo fuera el último índice con el que comenzar. Cuando el ciclo se ejecute para los otros elementos, terminará y una cosa u otra es cierta:
encontramos un nuevo valor máximo y, por lo tanto, un nuevo índice máximo mi
el último índice fue el valor máximo todo el tiempo, por lo que no encontramos uno nuevo miy nos quedamos con el valor inicialmi
El trabajo real lo realizan los modificadores posteriores al ciclo:
¿Es el valor máximo ( a[mi]es decir, la matriz indexada por mi) que encontramos hasta ahora, menor que el elemento actual?
sí, guarda uno nuevo mirecordandoi ,
no, entonces almacene el existente mi(no-op)
Al final de la operación, tiene el índice en el que se encuentra el máximo. Lógicamente, entonces el valor máximo esa[mi]
No pude ver cómo el "buscar el máximo y el índice de máximo" realmente necesitaba rastrear el valor máximo también, dado que si tiene una matriz y conoce el índice del valor máximo, el valor real del valor máximo es un caso trivial de usar el índice para indexar la matriz.
Respuestas:
Esta no es la forma más glamorosa, pero funciona.
(debe tener
using System.Linq;
)int maxValue = anArray.Max(); int maxIndex = anArray.ToList().IndexOf(maxValue);
fuente
.ToList()
implementación explícita de matricesIList
IList
interfaz, pero lo hacen explícitamente: msdn.microsoft.com/en-us/library/… . (Las matrices también implementan laIList<T>
interfaz genérica correspondiente .)ToList()
es copiar siempre. Sería una idea terrible que el método a veces se copiara y otras no; esto daría lugar a errores de alias bastante locos. De hecho, la implementación deToList()
es más o menosreturn new List(source)
int[] anArray = { 1, 5, 2, 7 }; // Finding max int m = anArray.Max(); // Positioning max int p = Array.IndexOf(anArray, m);
fuente
Si el índice no está ordenado, debe recorrer la matriz al menos una vez para encontrar el valor más alto. Usaría un
for
bucle simple :int? maxVal = null; //nullable so this works even if you have all super-low negatives int index = -1; for (int i = 0; i < anArray.Length; i++) { int thisNum = anArray[i]; if (!maxVal.HasValue || thisNum > maxVal.Value) { maxVal = thisNum; index = i; } }
Esto es más detallado que algo que usa LINQ u otras soluciones unifilares, pero probablemente sea un poco más rápido. Realmente no hay forma de hacer esto más rápido que O (N).
fuente
maxVal
con el valor de la matriz en el índice 0 (asumiendo que la matriz tiene al menos una longitud de 1),index
en 0 y comenzando el ciclo for eni = 1
.El LINQ one [1] -liner obligatorio:
var max = anArray.Select((value, index) => new {value, index}) .OrderByDescending(vi => vi.value) .First();
(La clasificación es probablemente un impacto en el rendimiento sobre las otras soluciones).
[1]: para valores dados de "uno".
fuente
Un breve resumen:
var max = anArray.Select((n, i) => (Number: n, Index: i)).Max();
Caso de prueba:
var anArray = new int[] { 1, 5, 2, 7 }; var max = anArray.Select((n, i) => (Number: n, Index: i)).Max(); Console.WriteLine($"Maximum number = {max.Number}, on index {max.Index}."); // Maximum number = 7, on index 4.
caracteristicas:
Observaciones:
fuente
anArray.Select((n, i) => ( Index: i, Number: n)).Max()
encuentra el índice máximo en lugar del número máximo debido a la forma en que se comparan las tuplas (el elemento 1 es el más significativo, etc.)Aquí hay dos enfoques. Es posible que desee agregar manejo para cuando la matriz esté vacía.
public static void FindMax() { // Advantages: // * Functional approach // * Compact code // Cons: // * We are indexing into the array twice at each step // * The Range and IEnumerable add a bit of overhead // * Many people will find this code harder to understand int[] array = { 1, 5, 2, 7 }; int maxIndex = Enumerable.Range(0, array.Length).Aggregate((max, i) => array[max] > array[i] ? max : i); int maxInt = array[maxIndex]; Console.WriteLine($"Maximum int {maxInt} is found at index {maxIndex}"); } public static void FindMax2() { // Advantages: // * Near-optimal performance int[] array = { 1, 5, 2, 7 }; int maxIndex = -1; int maxInt = Int32.MinValue; // Modern C# compilers optimize the case where we put array.Length in the condition for (int i = 0; i < array.Length; i++) { int value = array[i]; if (value > maxInt) { maxInt = value; maxIndex = i; } } Console.WriteLine($"Maximum int {maxInt} is found at index {maxIndex}"); }
fuente
anArray.Select((n, i) => new { Value = n, Index = i }) .Where(s => s.Value == anArray.Max());
fuente
int[] numbers = new int[7]{45,67,23,45,19,85,64}; int smallest = numbers[0]; for (int index = 0; index < numbers.Length; index++) { if (numbers[index] < smallest) smallest = numbers[index]; } Console.WriteLine(smallest);
fuente
Salida para el código de abajo:
00: 00: 00.3279270 - max1 00: 00: 00.2615935 - max2 00: 00: 00.6010360 - max3 (arr.Max ())
Con 100000000 ints en matriz, no es una gran diferencia, pero aún así ...
class Program { static void Main(string[] args) { int[] arr = new int[100000000]; Random randNum = new Random(); for (int i = 0; i < arr.Length; i++) { arr[i] = randNum.Next(-100000000, 100000000); } Stopwatch stopwatch1 = new Stopwatch(); Stopwatch stopwatch2 = new Stopwatch(); Stopwatch stopwatch3 = new Stopwatch(); stopwatch1.Start(); var max = GetMaxFullIterate(arr); Debug.WriteLine( stopwatch1.Elapsed.ToString()); stopwatch2.Start(); var max2 = GetMaxPartialIterate(arr); Debug.WriteLine( stopwatch2.Elapsed.ToString()); stopwatch3.Start(); var max3 = arr.Max(); Debug.WriteLine(stopwatch3.Elapsed.ToString()); } private static int GetMaxPartialIterate(int[] arr) { var max = arr[0]; var idx = 0; for (int i = arr.Length / 2; i < arr.Length; i++) { if (arr[i] > max) { max = arr[i]; } if (arr[idx] > max) { max = arr[idx]; } idx++; } return max; } private static int GetMaxFullIterate(int[] arr) { var max = arr[0]; for (int i = 0; i < arr.Length; i++) { if (arr[i] > max) { max = arr[i]; } } return max; }
fuente
public static class ArrayExtensions { public static int MaxIndexOf<T>(this T[] input) { var max = input.Max(); int index = Array.IndexOf(input, max); return index; } }
Esto funciona para todos los tipos de variables ...
var array = new int[]{1, 2, 4, 10, 0, 2}; var index = array.MaxIndexOf(); var array = new double[]{1.0, 2.0, 4.0, 10.0, 0.0, 2.0}; var index = array.MaxIndexOf();
fuente
public static void Main() { int a,b=0; int []arr={1, 2, 2, 3, 3, 4, 5, 6, 5, 7, 7, 7, 100, 8, 1}; for(int i=arr.Length-1 ; i>-1 ; i--) { a = arr[i]; if(a > b) { b=a; } } Console.WriteLine(b); }
fuente
int[] Data= { 1, 212, 333,2,12,3311,122,23 }; int large = Data.Max(); Console.WriteLine(large);
fuente
Aquí hay una solución LINQ que es O (n) con factores constantes decentes:
int[] anArray = { 1, 5, 2, 7, 1 }; int index = 0; int maxIndex = 0; var max = anArray.Aggregate( (oldMax, element) => { ++index; if (element <= oldMax) return oldMax; maxIndex = index; return element; } ); Console.WriteLine("max = {0}, maxIndex = {1}", max, maxIndex);
Pero realmente debería escribir un
for
lop explícito si le importa el rendimiento.fuente
Solo otra perspectiva usando
DataTable
. Declare aDataTable
con 2 columnas llamadasindex
yval
. Agregue unaAutoIncrement
opción y ambos valoresAutoIncrementSeed
y a la columna. Luego use un bucle e inserte cada elemento de la matriz en una fila. Luego, usando el método, seleccione la fila que tenga el valor máximo.AutoIncrementStep
1
index
foreach
datatable
Select
Código
int[] anArray = { 1, 5, 2, 7 }; DataTable dt = new DataTable(); dt.Columns.AddRange(new DataColumn[2] { new DataColumn("index"), new DataColumn("val")}); dt.Columns["index"].AutoIncrement = true; dt.Columns["index"].AutoIncrementSeed = 1; dt.Columns["index"].AutoIncrementStep = 1; foreach(int i in anArray) dt.Rows.Add(null, i); DataRow[] dr = dt.Select("[val] = MAX([val])"); Console.WriteLine("Max Value = {0}, Index = {1}", dr[0][1], dr[0][0]);
Salida
Max Value = 7, Index = 4
Encuentre una demostración aquí
fuente
Encuentra el número más grande y el más pequeño de la matriz:
int[] arr = new int[] {35,28,20,89,63,45,12}; int big = 0; int little = 0; for (int i = 0; i < arr.Length; i++) { Console.WriteLine(arr[i]); if (arr[i] > arr[0]) { big = arr[i]; } else { little = arr[i]; } } Console.WriteLine("most big number inside of array is " + big); Console.WriteLine("most little number inside of array is " + little);
fuente
Si conoce el índice máximo, el acceso al valor máximo es inmediato. Entonces todo lo que necesitas es un índice máximo.
int max=0; for(int i = 1; i < arr.Length; i++) if (arr[i] > arr[max]) max = i;
fuente
Esta es una versión de C #. Se basa en la idea de ordenar la matriz.
public int solution(int[] A) { // write your code in C# 6.0 with .NET 4.5 (Mono) Array.Sort(A); var max = A.Max(); if(max < 0) return 1; else for (int i = 1; i < max; i++) { if(!A.Contains(i)) { return i; } } return max + 1; }
fuente
Considere lo siguiente:
/// <summary> /// Returns max value /// </summary> /// <param name="arr">array to search in</param> /// <param name="index">index of the max value</param> /// <returns>max value</returns> public static int MaxAt(int[] arr, out int index) { index = -1; int max = Int32.MinValue; for (int i = 0; i < arr.Length; i++) { if (arr[i] > max) { max = arr[i]; index = i; } } return max; }
Uso:
int m, at; m = MaxAt(new int[]{1,2,7,3,4,5,6}, out at); Console.WriteLine("Max: {0}, found at: {1}", m, at);
fuente
Esto se puede hacer con un
for
bucle sin cuerpo , si nos dirigimos hacia el golf;)//a is the array int mi = a.Length - 1; for (int i=-1; ++i<a.Length-1; mi=a[mi]<a[i]?i:mi) ;
El cheque de
++i<a.Length-1
omite chequeando el último índice. No nos importa esto si lo configuramos como si el índice máximo fuera el último índice con el que comenzar. Cuando el ciclo se ejecute para los otros elementos, terminará y una cosa u otra es cierta:mi
mi
y nos quedamos con el valor inicialmi
El trabajo real lo realizan los modificadores posteriores al ciclo:
a[mi]
es decir, la matriz indexada pormi
) que encontramos hasta ahora, menor que el elemento actual?mi
recordandoi
,mi
(no-op)Al final de la operación, tiene el índice en el que se encuentra el máximo. Lógicamente, entonces el valor máximo es
a[mi]
No pude ver cómo el "buscar el máximo y el índice de máximo" realmente necesitaba rastrear el valor máximo también, dado que si tiene una matriz y conoce el índice del valor máximo, el valor real del valor máximo es un caso trivial de usar el índice para indexar la matriz.
fuente