C # findet den höchsten Array-Wert und Index

89

Ich habe also ein unsortiertes numerisches Array int[] anArray = { 1, 5, 2, 7 };und muss sowohl den Wert als auch den Index des größten Werts im Array abrufen, der 7 und 3 wäre. Wie würde ich das tun?

Edmund Rojas
quelle
Bisher habe ich versucht, die Max () -Methode zu verwenden und dann die binäre Suchmethode zu verwenden, um den Index dieses Maximalwerts zu erhalten. Dies funktioniert jedoch nur, wenn das Array sortiert ist, sodass ich es nicht verwenden kann, als ich versuchte, negative Zahlen zu erhalten
Edmund Rojas
@EdmundRojas Sie müssen keine binäre Suche verwenden. Eine einfache alte lineare Suche funktioniert gut für unsortierte Listen.
Millimoose

Antworten:

137

Dies ist nicht der glamouröseste Weg, sondern funktioniert.

(muss haben using System.Linq;)

 int maxValue = anArray.Max();
 int maxIndex = anArray.ToList().IndexOf(maxValue);
sa_ddam213
quelle
9
Sie sparen viel Zeit beim Codieren, gehen die Sammlung jedoch zweimal durch.
Garo Yeriazarian
10
Sie brauchen nicht einmal die .ToList()Arrays explizit zu implementierenIList
Millimoose
@GaroYeriazarian Wenn die lineare Komplexität für Ihren Anwendungsfall zu groß ist, müssen Sie wahrscheinlich mehr als nur den konstanten Faktor um ein Drittel reduzieren. (Obwohl es offensichtlich keine vernachlässigbare Optimierung ist.)
Millimoose
1
@ sa_ddam213 Arrays implementieren die IList Schnittstelle, tun dies jedoch explizit: msdn.microsoft.com/en-us/library/… . (Arrays implementieren auch die entsprechende generische IList<T>Schnittstelle.)
Millimoose
1
@ sa_ddam213 Nein, der Vertrag von ToList()ist immer zu kopieren. Es wäre eine schreckliche Idee, die Methode manchmal kopieren zu lassen und manchmal nicht - dies würde zu ziemlich verrückten Aliasing-Fehlern führen. In der Tat von der Implementierung ToList()ist mehr oder wenigerreturn new List(source)
millimoose
42
int[] anArray = { 1, 5, 2, 7 };
// Finding max
int m = anArray.Max();

// Positioning max
int p = Array.IndexOf(anArray, m);
asr
quelle
27

Wenn der Index nicht sortiert ist, müssen Sie das Array mindestens einmal durchlaufen, um den höchsten Wert zu finden. Ich würde eine einfache verwendenfor Schleife verwenden:

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;
  }
}

Dies ist ausführlicher als etwas, das LINQ oder andere einzeilige Lösungen verwendet, aber es ist wahrscheinlich etwas schneller. Es gibt wirklich keine Möglichkeit, dies schneller als O (N) zu machen.

Tom Hamming
quelle
3
Sie können eine Iteration speichern, indem Sie maxValden Indexwert bei Index 0 (vorausgesetzt, das Array hat mindestens die Länge 1) indexauf 0 initialisieren und die for-Schleife bei starten i = 1.
Jon Schneider
13

Der obligatorische LINQ one [1] -Liner:

var max = anArray.Select((value, index) => new {value, index})
                 .OrderByDescending(vi => vi.value)
                 .First();

(Die Sortierung ist wahrscheinlich ein Leistungseinbruch gegenüber den anderen Lösungen.)

[1]: Für gegebene Werte von "eins".

Millimoose
quelle
13
Nur um diese Lösung hinzuzufügen, ist bestenfalls O (nlogn) Komplexität. Das Finden von max kann in O (n) Zeit für ein unsortiertes Array erhalten werden.
Dopplesoldner
12

Ein prägnanter Einzeiler:

var max = anArray.Select((n, i) => (Number: n, Index: i)).Max();

Testfall:

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.

Eigenschaften:

  • Verwendet Linq (nicht so optimiert wie Vanille, aber der Kompromiss ist weniger Code).
  • Muss nicht sortieren.
  • Rechenkomplexität: O (n).
  • Raumkomplexität: O (n).
Lesair Valmont
quelle
das ist wirklich ordentlich !!
Floydheld
3

Hier sind zwei Ansätze. Möglicherweise möchten Sie eine Behandlung hinzufügen, wenn das Array leer ist.

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}");
}
Neil
quelle
1
anArray.Select((n, i) => new { Value = n, Index = i })
    .Where(s => s.Value == anArray.Max());
Adam Nathan
quelle
Dies ist eine O (n ^ 2) -Lösung, da Sie bei jeder Iteration anArray.Max () berechnen. Bei großen Arrays wird das sehr langsam.
Neil
1
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);
GEEK
quelle
1

Ausgabe für folgenden Code:

00: 00: 00.3279270 - max1 00: 00: 00.2615935 - max2 00: 00: 00.6010360 - max3 (arr.Max ())

Mit 100000000 Ints im Array kein großer Unterschied, aber dennoch ...

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;
        }
Andreas
quelle
1
 public static class ArrayExtensions
{
    public static int MaxIndexOf<T>(this T[] input)
    {
        var max = input.Max();
        int index = Array.IndexOf(input, max);
        return index;
    }
}

Dies funktioniert für alle Variablentypen ...

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();
Joe Sonderegger
quelle
1
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);
}

quelle
0
int[] Data= { 1, 212, 333,2,12,3311,122,23 };
int large = Data.Max();
Console.WriteLine(large);
Jeetendra Negi
quelle
1
Ihre Antwort gibt nur den höchsten Wert an, aber der Fragesteller hat sowohl den höchsten Wert als auch den Index des höchsten Werts angefordert.
Cardin
0

Hier ist eine LINQ-Lösung, die O (n) mit anständigen konstanten Faktoren ist:

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);

Aber Sie sollten wirklich einen expliziten forLop schreiben, wenn Sie Wert auf Leistung legen.

Branko Dimitrijevic
quelle
0

Nur eine andere Perspektive mit DataTable. Deklarieren Sie a DataTablemit 2 Spalten indexund val. Fügen Sie der Spalte eine AutoIncrementOption und beide AutoIncrementSeedund AutoIncrementStepWerte hinzu . Verwenden Sie dann eine Schleife und fügen Sie jedes Array-Element als Zeile in das ein. Wählen Sie dann mit der Methode die Zeile mit dem Maximalwert aus.1indexforeachdatatableSelect

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]);

Ausgabe

Max Value = 7, Index = 4

Hier finden Sie eine Demo

Ullas
quelle
0

Findet die größte und die kleinste Zahl im Array:

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);
Javidan Akberov
quelle
1
Es wird der letzte Wert zurückgegeben, der größer / kleiner als der erste Wert im Array ist, nicht der min / max.
Tomer Wolberg
0

Wenn Sie wissen, dass der maximale Indexzugriff sofort erfolgt, erfolgt der maximale Wert. Alles was Sie brauchen ist der maximale Index.

int max=0;

for(int i = 1; i < arr.Length; i++)
    if (arr[i] > arr[max]) max = i;
Alex Peter
quelle
0

Dies ist eine C # -Version. Es basiert auf der Idee, das Array zu sortieren.

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;
}
Judavi
quelle
0

Beachten Sie Folgendes:

    /// <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;
    }

Verwendung:

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);
BogdanRB
quelle