C # знайти найвище значення масиву та індекс


92

Отже, у мене є несортований числовий масив, int[] anArray = { 1, 5, 2, 7 };і мені потрібно отримати як значення, так і індекс найбільшого значення в масиві, яке було б 7 і 3, як би я це зробив?


Поки що я намагався використовувати метод Max (), а потім використовував двійковий метод пошуку, щоб отримати індекс цього максимального значення, але це не працює, якщо масив не відсортований, тому я не можу його використовувати, коли я намагався, що це дало мені від'ємні числа
Едмунд Рохас

@EdmundRojas Вам не потрібно використовувати двійковий пошук. Звичайний лінійний пошук чудово працює для невідсортованих списків.
milimoose

Відповіді:


144

Це не самий гламурний спосіб, але працює.

(повинен бути using System.Linq;)

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

11
Ви економите багато часу на кодування, але в підсумку ви пройдете колекцію двічі.
Garo Yeriazarian

11
Вам навіть не потрібні .ToList()масиви, явно реалізованіIList
milimoose

@GaroYeriazarian Якщо лінійна складність занадто велика для вашого випадку використання, вам, мабуть, потрібно збрити більше, ніж просто зменшити постійний коефіцієнт на третину. (Хоча, очевидно, це не мізерна оптимізація.)
milimoose

1
@ sa_ddam213 Масиви реалізують IListінтерфейс, але вони роблять це явно: msdn.microsoft.com/en-us/library/… . (Масиви також реалізують відповідний загальний IList<T>інтерфейс.)
milimoose

1
@ sa_ddam213 Ні, контрактом ToList()завжди є копіювання. Було б жахливою ідеєю мати метод, який іноді копіюється, а іноді ні - це призведе до досить шалених помилок згладжування. Насправді реалізація ToList()більш-меншreturn new List(source)
мілімуз

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

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

28

Якщо індекс не відсортований, вам доведеться хоча б раз перебирати масив, щоб знайти найвище значення. Я б використав простий forцикл:

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

Це більш багатослівно, ніж щось, що використовується LINQ чи інші однолінійні рішення, але це, можливо, трохи швидше. Насправді немає можливості зробити це швидше, ніж O (N).


4
Ви можете зберегти одну ітерацію, ініціалізувавши maxValзначення масиву з індексом 0 (якщо припустимо, що масив має принаймні довжину 1), indexдо 0 і запустивши цикл for на i = 1.
Джон Шнайдер

14

Обов’язковий LINQ один [1] -ліній:

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

(Сортування, мабуть, є успіхом порівняно з іншими рішеннями.)

[1]: Для заданих значень "одиниця".


14
Просто додати це рішення - це O (nlogn) складність у кращому випадку. Знаходження max можна отримати за час O (n) для невідсортованого масиву.
dopplesoldner

13

Короткий лайнер:

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

Тестовий приклад:

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.

Особливості:

  • Використовує Linq (не настільки оптимізований, як ваніль, але компроміс менше коду).
  • Не потрібно сортувати.
  • Складність обчислень: O (n).
  • Складність простору: O (n).

Примітки:

  • Переконайтеся, що число (а не індекс) є першим елементом кортежу, оскільки сортування кортежів здійснюється шляхом порівняння елементів кортежу зліва направо.

це дійсно акуратно !!
floydheld

Слід зазначити, що для того, щоб це могло спрацювати, предмет, що підлягає максимуму, повинен бути першим
Кай Ярд

Що ви маєте на увазі @CaiusJard? Як показано в тестовому прикладі, максимальний предмет був правильно знайдений і останній.
Лесейр Вальмонт,

Спочатку в Кортежі, наприклад, anArray.Select((n, i) => ( Index: i, Number: n)).Max()знаходить максимальний індекс, а не максимальне число, через спосіб порівняння кортежів (item1 є найбільш значущим тощо)
Caius Jard

Досить справедливо @CaiusJard, я додав зауваження, щоб зазначити це. Дякую.
Lesair Valmont

3

Ось два підходи. Можливо, ви захочете додати обробку, коли масив порожній.

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

Це рішення O (n ^ 2), оскільки ви обчислюєте anArray.Max () на кожній ітерації. Це стане дуже повільним для великих масивів.
Ніл,

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

Вихідні дані для нижченаведеного коду:

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

З масивом 100000000 ints не дуже велика різниця, але все ж ...

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

Це працює для всіх типів змінних ...

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
Ваша відповідь дає лише найвище значення, але запитувач вимагає як найвище значення, так і індекс найвищого значення.
Cardin

0

Ось рішення LINQ, яке є O (n) з пристойними постійними коефіцієнтами:

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

Але вам дійсно слід написати явний forлоп, якщо ви дбаєте про продуктивність.


0

Просто інша перспектива використання DataTable. Оголосіть a DataTableдвома стовпцями, що викликаються indexта val. Додайте AutoIncrementопцію та обидва значення, AutoIncrementSeedі AutoIncrementStepзначення 1до indexстовпця. Потім використовуйте foreachцикл і вставте кожен елемент масиву datatableв рядок як. Потім за допомогоюSelect метод, виберіть рядок, що має максимальне значення.

Код

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

Вихідні дані

Max Value = 7, Index = 4

Знайдіть демо тут


0

Знаходить найбільше і найменше число в масиві:

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
він поверне останнє значення, яке більше / менше, ніж перше значення в масиві, а не мінімальне / максимальне.
Томер Волберг,

0

Якщо ви знаєте максимальний індекс, доступ до максимального значення відбувається негайно. Отже, все, що вам потрібно - це максимальний індекс.

int max=0;

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

0

Це версія C #. Він заснований на ідеї сортування масиву.

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

Розгляньте наступне:

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

Використання:

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

Це можна зробити за допомогою безтілесної forпетлі, якщо ми рухаємось до гольфу;)

//a is the array


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

Перевірка ++i<a.Length-1пропусків перевірки останнього індексу. Ми не заперечуємо перед цим, якщо ми встановлюємо його так, ніби максимальний індекс є останнім індексом, з якого починається .. Коли цикл запускається для інших елементів, він закінчується, і одна або інша річ істинна:

  • ми знайшли нове максимальне значення і, отже, новий максимальний індекс mi
  • останній індекс був максимальним значенням весь час, тому ми не знайшли нового mi, і ми дотрималися початковогоmi

Справжню роботу виконують модифікатори після циклу:

  • чи максимальне значення ( a[mi]тобто індексований масив mi), яке ми знайшли до цього часу, менше, ніж поточний елемент?
    • так, тоді зберігайте нове mi, пам’ятаючиi ,
    • ні тоді зберігати існуючі mi(no-op)

В кінці операції ви отримаєте індекс, за яким буде знайдено максимум. Логічно, тоді максимальне значення дорівнюєa[mi]

Я не міг зрозуміти, як "знайти максимум та індекс максимуму" дійсно потрібно було також відстежувати максимальне значення, враховуючи, що якщо у вас є масив, і ви знаєте індекс максимального значення, фактичне значення максимального значення тривіальний випадок використання індексу для індексації масиву ..

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.