C # menemukan nilai array dan indeks tertinggi


93

Jadi saya memiliki array numerik yang tidak diurutkan int[] anArray = { 1, 5, 2, 7 };dan saya perlu mendapatkan nilai dan indeks dari nilai terbesar dalam array yang akan menjadi 7 dan 3, bagaimana saya melakukan ini?


Sejauh ini saya mencoba menggunakan metode Max () dan kemudian menggunakan metode pencarian biner untuk mendapatkan indeks dari nilai maks itu tetapi ini tidak berfungsi kecuali array diurutkan jadi saya tidak dapat menggunakannya, ketika saya mencoba itu memberi saya angka negatif
Edmund Rojas

@EdmundRojas Anda tidak perlu menggunakan pencarian biner. Pencarian linier biasa bekerja dengan baik untuk daftar yang tidak diurutkan.
millimoose

Jawaban:


145

Ini bukan cara yang paling glamor tapi berhasil.

(harus punya using System.Linq;)

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

11
Anda menghemat banyak waktu pengkodean, tetapi pada akhirnya Anda akan melalui pengumpulan dua kali.
Garo Yeriazarian

11
Anda bahkan tidak memerlukan .ToList(), larik yang diimplementasikan secara eksplisitIList
millimoose

@GaroYeriazarian Jika kompleksitas linier terlalu banyak untuk kasus penggunaan Anda, Anda mungkin perlu mengurangi lebih dari sekadar mengurangi faktor konstanta sepertiga. (Meskipun jelas ini bukan pengoptimalan yang dapat diabaikan.)
millimoose

1
@ sa_ddam213 Array mengimplementasikan IListantarmuka, tetapi mereka melakukannya secara eksplisit: msdn.microsoft.com/en-us/library/… . (Array juga menerapkan IList<T>antarmuka umum yang sesuai .)
millimoose

1
@ sa_ddam213 Tidak, kontraknya ToList()adalah untuk selalu menyalin. Akan menjadi ide yang buruk untuk memiliki metode yang kadang-kadang menyalin dan terkadang tidak - ini akan menyebabkan bug aliasing yang cukup gila. Faktanya penerapannya ToList()lebih atau kurangreturn 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

Jika indeks tidak diurutkan, Anda harus mengulang melalui array setidaknya sekali untuk menemukan nilai tertinggi. Saya akan menggunakan forloop sederhana :

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

Ini lebih bertele-tele daripada sesuatu yang menggunakan LINQ atau solusi satu baris lainnya, tetapi mungkin sedikit lebih cepat. Benar-benar tidak ada cara untuk membuat ini lebih cepat dari O (N).


4
Anda dapat menyimpan satu iterasi dengan menginisialisasi maxValke nilai array pada indeks 0 (dengan asumsi array setidaknya panjang 1), indexke 0, dan memulai perulangan for di i = 1.
Jon Schneider

14

LINQ wajib satu [1] -liner:

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

(Penyortiran mungkin merupakan kinerja yang terpukul di atas solusi lain.)

[1]: Untuk nilai "satu" yang diberikan.


14
Hanya untuk menambahkan solusi ini adalah kompleksitas O (nlogn) yang terbaik. Menemukan nilai maks dapat diperoleh dalam waktu O (n) untuk larik yang tidak disortir.
dopplesoldner

13

Satu kalimat yang ringkas:

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

Kasus cobaan:

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.

Fitur:

  • Menggunakan Linq (tidak dioptimalkan seperti vanilla, tetapi trade-offnya adalah lebih sedikit kode).
  • Tidak perlu diurutkan.
  • Kompleksitas komputasi: O (n).
  • Kompleksitas ruang: O (n).

Catatan:

  • Pastikan nomor (dan bukan indeks) adalah elemen pertama dalam tupel karena penyortiran tupel dilakukan dengan membandingkan item tupel dari kiri ke kanan.

ini sangat rapi !!
floydheld

Harus ditunjukkan bahwa agar ini berfungsi, item yang dimaksimalkan harus terlebih dahulu
Caius Jard

Apa maksudmu @CaiusJard? Seperti yang ditunjukkan dalam kasus uji, item maksimum ditemukan dengan benar dan terakhir.
Lesair Valmont

Pertama di Tuple, misalnya anArray.Select((n, i) => ( Index: i, Number: n)).Max()menemukan indeks maks daripada jumlah maks karena cara tupel dibandingkan (item1 paling signifikan dll)
Caius Jard

Cukup adil @CaiusJard, saya menambahkan komentar untuk menunjukkannya. Terima kasih.
Lesair Valmont

3

Berikut dua pendekatan. Anda mungkin ingin menambahkan penanganan saat array kosong.

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

Ini adalah solusi O (n ^ 2), karena Anda menghitung anArray.Max () pada setiap iterasi. Itu akan menjadi sangat lambat untuk array besar.
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

Output untuk kode di bawah ini:

00: 00: 00.3279270 - maks1 00: 00: 00.2615935 - maks2 00: 00: 00.6010360 - maks3 (arr.Max ())

Dengan 100000000 int dalam array perbedaan yang tidak terlalu besar tetapi masih ...

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

Ini berfungsi untuk semua jenis variabel ...

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
Jawaban Anda hanya memberikan nilai tertinggi, tetapi penanya meminta nilai tertinggi dan indeks dari nilai tertinggi.
Cardin

0

Berikut adalah solusi LINQ yaitu O (n) dengan faktor konstanta yang layak:

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

Tetapi Anda harus benar-benar menulis forlop eksplisit jika Anda peduli dengan kinerja.


0

Hanya menggunakan perspektif lain DataTable. Deklarasikan a DataTabledengan 2 kolom yang disebut indexdan val. Tambahkan AutoIncrementopsi dan keduanya AutoIncrementSeedserta AutoIncrementStepnilai 1ke indexkolom. Kemudian gunakan foreachloop dan masukkan setiap item array ke dalam datatablebaris sebagai. Kemudian dengan menggunakan Selectmetode, pilih baris yang memiliki nilai maksimum.

Kode

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

Keluaran

Max Value = 7, Index = 4

Temukan demo di sini


0

Menemukan angka terbesar dan terkecil dalam 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
itu akan mengembalikan nilai terakhir yang lebih besar / lebih kecil dari nilai pertama dalam larik, bukan min / maks.
Tomer Wolberg

0

Jika Anda tahu indeks maks mengakses nilai maks langsung. Jadi yang Anda butuhkan hanyalah indeks maks.

int max=0;

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

0

Ini adalah Versi C #. Ini didasarkan pada gagasan mengurutkan array.

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

Pertimbangkan berikut ini:

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

Pemakaian:

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

Ini bisa dilakukan dengan forloop tanpa tubuh, jika kita menuju 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) ;

Pemeriksaan ++i<a.Length-1kelalaian memeriksa indeks terakhir. Kami tidak keberatan jika kami mengaturnya seolah-olah indeks maks adalah indeks terakhir untuk memulai .. Ketika loop berjalan untuk elemen lain, itu akan selesai dan satu atau hal lain benar:

  • kami menemukan nilai maks baru dan karenanya indeks maks baru mi
  • indeks terakhir adalah nilai maksimal selama ini, jadi kami tidak menemukan yang baru mi, dan kami terjebak dengan yang awalmi

Pekerjaan sebenarnya dilakukan oleh pengubah post-loop:

  • adalah nilai maks ( a[mi]yaitu array yang diindeks oleh mi) yang kami temukan sejauh ini, kurang dari item saat ini?
    • ya, lalu simpan yang baru midengan mengingat i,
    • tidak maka simpan yang ada mi(no-op)

Di akhir operasi Anda memiliki indeks di mana nilai maksimum dapat ditemukan. Logikanya, nilai maksimalnya adalaha[mi]

Saya tidak bisa melihat bagaimana "temukan maks dan indeks maks" benar-benar diperlukan untuk melacak nilai maks juga, mengingat jika Anda memiliki larik, dan Anda tahu indeks nilai maks, nilai sebenarnya dari nilai maks adalah kasus sepele menggunakan indeks untuk mengindeks larik ..

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.