C # en yüksek dizi değerini ve dizini bulur


92

Yani sıralanmamış bir sayısal dizim var int[] anArray = { 1, 5, 2, 7 };ve dizideki en büyük değerin hem değerini hem de dizinini almam gerekiyor ki bu 7 ve 3 olacaktır, bunu nasıl yapacağım?


Şimdiye kadar Max () yöntemini kullanmayı denedim ve ardından bu maksimum değerin dizinini almak için ikili arama yöntemini kullandım, ancak dizi sıralanmadıkça bu işe yaramıyor, bu yüzden kullanamıyorum, bana negatif sayılar vermeyi denediğimde
Edmund Rojas

@EdmundRojas İkili aramayı kullanmanıza gerek yok. Düz ol 'doğrusal arama, sıralanmamış listeler için gayet iyi çalışır.
millimoose

Yanıtlar:


144

Bu en göz alıcı yol değil ama işe yarıyor.

(olmalı using System.Linq;)

 int maxValue = anArray.Max();
 int maxIndex = anArray.ToList().IndexOf(maxValue);

11
Çok fazla kodlama süresinden tasarruf edersiniz, ancak koleksiyonu iki kez gözden geçireceksiniz.
Garo Yeriazarian

11
.ToList()Dizilerin açıkça uygulanmasına bile ihtiyacınız yokIList
millimoose

@GaroYeriazarian Doğrusal karmaşıklık kullanım durumunuz için çok fazlaysa, muhtemelen sabit faktörü üçte bir oranında azaltmaktan daha fazlasını kesmeniz gerekir. (Açıkçası göz ardı edilebilir bir optimizasyon olmasa da.)
millimoose

1
@ sa_ddam213 Diziler IListarabirimi uygular , ancak bunu açıkça yaparlar: msdn.microsoft.com/en-us/library/… . (Diziler ayrıca ilgili genel IList<T>arabirimi de uygular .)
millimoose

1
@ sa_ddam213 Hayır, sözleşmesi ToList()her zaman kopyalamaktır. Yöntemin bazen kopyalanması bazen de kopyalanmaması korkunç bir fikir olurdu - bu oldukça çılgınca takma ad hatalarına yol açar. Aslında, uygulaması ToList()aşağı yukarıreturn new List(source)
millimoose

44
int[] anArray = { 1, 5, 2, 7 };
// Finding max
int m = anArray.Max();

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

28

Dizin sıralanmamışsa, en yüksek değeri bulmak için dizide en az bir kez yineleme yapmanız gerekir. Basit bir fordöngü kullanırım:

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

Bu, LINQ veya diğer tek satırlık çözümleri kullanan bir şeyden daha ayrıntılıdır, ancak muhtemelen biraz daha hızlıdır. Bunu O (N) 'den daha hızlı yapmanın gerçekten bir yolu yok.


4
maxVal0 dizinindeki dizi değerini (dizinin en az 1 uzunluğunda olduğu varsayılarak) index0'a başlatarak ve for döngüsünü de başlatarak bir yineleme kaydedebilirsiniz i = 1.
Jon Schneider

14

Zorunlu LINQ one [1] -liner:

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

(Sıralama, muhtemelen diğer çözümlere göre bir performans artışıdır.)

[1]: Verilen "bir" değerleri için.


14
Sadece bu çözümü eklemek, en iyi ihtimalle O (nlogn) karmaşıklığıdır. Maksimum bulma, sıralanmamış bir dizi için O (n) zamanında elde edilebilir.
dopplesoldner

13

Kısa ve öz bir tek satır:

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

Test durumu:

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.

Özellikleri:

  • Linq kullanır (vanilya kadar optimize edilmemiştir, ancak takas daha az koddur).
  • Sıralamaya gerek yoktur.
  • Hesaplama karmaşıklığı: O (n).
  • Uzay karmaşıklığı: O (n).

Uyarılar:

  • Tuple'daki ilk öğe sayının (dizinin değil) olduğundan emin olun, çünkü tuple sıralama, tuple öğelerini soldan sağa karşılaştırarak yapılır.

bu gerçekten harika !!
floydheld

Bunun işe yaraması için, maksimize edilen öğenin ilk olması gerektiği belirtilmelidir
Caius Jard

@CaiusJard ne demek? Test senaryosunda gösterildiği gibi, maksimum öğe doğru bir şekilde bulundu ve en sonuncuydu.
Lesair Valmont

İlk olarak Tuple'da, örneğin anArray.Select((n, i) => ( Index: i, Number: n)).Max()tuple'ların karşılaştırılma şekli nedeniyle maksimum sayı yerine maksimum indeksi bulur (öğe1 en önemli olanı vb.)
Caius Jard

Yeterince adil @CaiusJard, bunu belirtmek için bir açıklama ekledim. Teşekkürler.
Lesair Valmont

3

İşte iki yaklaşım. Dizi boş olduğunda işlem eklemek isteyebilirsiniz.

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

Bu bir O (n ^ 2) çözümüdür, çünkü her yinelemede bir Array.Max () öğesini hesaplıyorsunuz. Bu, büyük diziler için çok yavaşlayacaktır.
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

Aşağıdaki kod için çıktı:

00: 00: 00.3279270 - maks1 00: 00: 00.2615935 - maks2 00: 00: 00.6010360 - maks3 (aralık.Maks ())

Dizideki 100000000 inç ile çok büyük bir fark değil ama yine de ...

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

Bu, tüm değişken türleri için çalışır ...

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
Cevabınız yalnızca en yüksek değeri verir, ancak soruyu soran kişi hem en yüksek değeri hem de en yüksek değerin endeksini ister.
Cardin

0

İşte iyi sabit faktörlerle O (n) olan bir LINQ çözümü:

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

Ancak forperformansı önemsiyorsanız , gerçekten açık bir söz yazmalısınız .


0

Sadece başka bir perspektif kullanarak DataTable. Ve DataTableadlı 2 sütunlu bir beyan edin . Bir ekleme seçeneği ve her ikisi ve değerler için sütunda. Sonra bir döngü kullanın ve her dizi öğesini bir satır olarak ekleyin . Daha sonra yöntemi kullanarak maksimum değere sahip satırı seçin.indexvalAutoIncrementAutoIncrementSeedAutoIncrementStep1indexforeachdatatableSelect

Kod

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

Çıktı

Max Value = 7, Index = 4

Burada bir demo bulun


0

Dizideki en büyük ve en küçük sayıyı bulur:

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
min / max değil, dizideki ilk değerden daha büyük / küçük olan son değeri döndürecektir.
Tomer Wolberg

0

Maksimum değere erişimin maksimum indeksini biliyorsanız hemen olur. Yani ihtiyacınız olan tek şey maksimum indeks.

int max=0;

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

0

Bu bir C # Sürümüdür. Diziyi sıralama fikrine dayanıyor.

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

Aşağıdakileri düşünün:

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

Kullanım:

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

0

Bu, forgolfe doğru gidersek, bedensiz bir döngü ile yapılabilir ;)

//a is the array


int mi = a.Length - 1;
for (int i=-1; ++i<a.Length-1; mi=a[mi]<a[i]?i:mi) ;

Onay ++i<a.Length-1son endeksini kontrol atlar. Bunu, maks. İndeks başlayacak son indeksmiş gibi ayarlarsak bunu umursamayız .. Döngü diğer öğeler için çalıştığında biter ve bir veya diğer şey doğrudur:

  • yeni bir maksimum değer ve dolayısıyla yeni bir maksimum indeks bulduk mi
  • son indeks başından beri maksimum değerdi, bu yüzden yeni bir tane bulamadık mive baştakimi

Gerçek iş, döngü sonrası değiştiriciler tarafından yapılır:

  • şu ana kadar bulduğumuz maksimum değer ( a[mi]yani dizine göre dizine alınmış mi), mevcut öğeden daha mı az?
    • evet, o zaman mihatırlayarak yenisini saklayıni ,
    • hayır o zaman var olanı sakla mi(işlemsiz)

İşlemin sonunda maksimumun bulunacağı dizine sahipsiniz. Mantıksal olarak maksimum değer şu şekildedir:a[mi]

Bir diziniz varsa ve maksimum değerin dizinini, maksimum değerin gerçek değerini biliyorsanız, maksimum değeri izlemek için gerçekten de "maks ve maksimum indeksini bul" un nasıl gerekli olduğunu tam olarak anlayamadım diziyi indekslemek için indeksi kullanmanın önemsiz bir durumudur ..

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.