J'ai donc un tableau numérique non trié int[] anArray = { 1, 5, 2, 7 };
et j'ai besoin d'obtenir à la fois la valeur et l'index de la plus grande valeur du tableau qui serait 7 et 3, comment puis-je faire cela?
J'ai donc un tableau numérique non trié int[] anArray = { 1, 5, 2, 7 };
et j'ai besoin d'obtenir à la fois la valeur et l'index de la plus grande valeur du tableau qui serait 7 et 3, comment puis-je faire cela?
Réponses:
Ce n'est pas la manière la plus glamour mais ça marche.
(doit avoir using System.Linq;
)
int maxValue = anArray.Max();
int maxIndex = anArray.ToList().IndexOf(maxValue);
.ToList()
implémentation explicite des tableaux,IList
IList
interface, mais ils le font explicitement: msdn.microsoft.com/en-us/library/… . (Les tableaux implémentent également l' IList<T>
interface générique correspondante .)
ToList()
est de toujours copier. Ce serait une idée terrible d'avoir la méthode parfois copiée et parfois non - cela conduirait à des bogues d'alias assez fous. En fait, la mise en œuvre de ToList()
est plus ou moinsreturn new List(source)
Si l'index n'est pas trié, vous devez parcourir le tableau au moins une fois pour trouver la valeur la plus élevée. J'utiliserais une for
boucle 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;
}
}
C'est plus détaillé que quelque chose utilisant LINQ ou d'autres solutions en une ligne, mais c'est probablement un peu plus rapide. Il n'y a vraiment aucun moyen de rendre cela plus rapide que O (N).
maxVal
à la valeur du tableau à l'index 0 (en supposant que le tableau a au moins la longueur 1), index
à 0 et en commençant la boucle for à i = 1
.
Le LINQ one [1] -liner obligatoire:
var max = anArray.Select((value, index) => new {value, index})
.OrderByDescending(vi => vi.value)
.First();
(Le tri est probablement un impact sur les performances par rapport aux autres solutions.)
[1]: Pour des valeurs données de "un".
Un one-liner succinct:
var max = anArray.Select((n, i) => (Number: n, Index: i)).Max();
Cas de test:
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.
Fonctionnalités:
Remarques:
anArray.Select((n, i) => ( Index: i, Number: n)).Max()
trouve l'index max plutôt que le nombre max en raison de la façon dont les tuples sont comparés (item1 est le plus significatif, etc.)
Voici deux approches. Vous souhaiterez peut-être ajouter une gestion lorsque le tableau est vide.
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}");
}
anArray.Select((n, i) => new { Value = n, Index = i })
.Where(s => s.Value == anArray.Max());
Sortie pour le code ci-dessous:
00: 00: 00.3279270 - max1 00: 00: 00.2615935 - max2 00: 00: 00.6010360 - max3 (arr.Max ())
Avec 100000000 ints en tableau, ce n'est pas une très grande différence mais quand même ...
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;
}
public static class ArrayExtensions
{
public static int MaxIndexOf<T>(this T[] input)
{
var max = input.Max();
int index = Array.IndexOf(input, max);
return index;
}
}
Cela fonctionne pour tous les types 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();
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);
}
int[] Data= { 1, 212, 333,2,12,3311,122,23 };
int large = Data.Max();
Console.WriteLine(large);
Voici une solution LINQ qui est O (n) avec des facteurs constants décents:
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);
Mais vous devriez vraiment écrire un for
lop explicite si vous vous souciez des performances.
Juste une autre perspective utilisant DataTable
. Déclarez un DataTable
avec 2 colonnes appelées index
et val
. Ajoutez une AutoIncrement
option et des valeurs AutoIncrementSeed
et à la colonne. Ensuite, utilisez une boucle et insérez chaque élément de tableau dans le sous forme de ligne. Ensuite, en utilisant method, sélectionnez la ligne ayant la valeur maximale.AutoIncrementStep
1
index
foreach
datatable
Select
Code
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]);
Production
Max Value = 7, Index = 4
Recherche le plus grand et le plus petit nombre du tableau:
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);
Si vous connaissez max index, l'accès à la valeur max est immédiat. Donc, tout ce dont vous avez besoin est un index max.
int max=0;
for(int i = 1; i < arr.Length; i++)
if (arr[i] > arr[max]) max = i;
Ceci est une version C #. Il est basé sur l'idée de trier le tableau.
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;
}
Pensez à suivre:
/// <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;
}
Usage:
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);
Cela peut être fait avec une for
boucle sans corps, si nous nous dirigeons vers le 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) ;
Le contrôle des ++i<a.Length-1
omet de vérifier le dernier index. Cela ne nous dérange pas si nous le configurons comme si l'index max était le dernier index avec lequel commencer. Lorsque la boucle s'exécute pour les autres éléments, elle se terminera et l'une ou l'autre chose est vraie:
mi
mi
, et nous sommes restés avec l'initialemi
Le vrai travail est effectué par les modificateurs post-boucle:
a[mi]
c'est-à-dire le tableau indexé par mi
) que nous avons trouvée jusqu'à présent, inférieure à l'élément actuel?
mi
en se souvenant i
,mi
(no-op)À la fin de l'opération, vous avez l'index auquel le max doit être trouvé. Logiquement, la valeur maximale esta[mi]
Je ne pouvais pas vraiment voir comment le "find max and index of max" avait vraiment besoin de suivre la valeur max, étant donné que si vous avez un tableau et que vous connaissez l'indice de la valeur max, la valeur réelle de la valeur max est un cas trivial d'utilisation de l'index pour indexer le tableau.