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?


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

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

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.


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".


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

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

1
anArray.Select((n, i) => new { Value = n, Index = i })
    .Where(s => s.Value == anArray.Max());

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

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

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

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

0
int[] Data= { 1, 212, 333,2,12,3311,122,23 };
int large = Data.Max();
Console.WriteLine(large);

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.


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


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

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;

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

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);
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.