С # найти максимальное значение массива и индекс


92

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


До сих пор ive пытался использовать метод Max (), а затем использовать метод двоичного поиска, чтобы получить индекс этого максимального значения, но это не работает, если массив не отсортирован, поэтому я не могу его использовать, когда я пытался, что он дал мне отрицательные числа
— Эдмунд Рохас

@EdmundRojas Вам не нужно использовать двоичный поиск. Обычный линейный поиск отлично подходит для несортированных списков.
— millimoose

Ответы:


144

Это не самый гламурный способ, но работает.

(должно быть using System.Linq;)

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

11
Вы сэкономите много времени на кодирование, но в конечном итоге вам придется дважды просмотреть коллекцию.
— Гаро Ериязарян

11
Вам даже не нужно .ToList()явно реализовывать массивыIList
— millimoose

@GaroYeriazarian Если линейная сложность слишком велика для вашего варианта использования, вам, вероятно, нужно сбрить больше, чем просто уменьшить постоянный коэффициент на треть. (Хотя, очевидно, это не незначительная оптимизация.)
— millimoose

1
@ sa_ddam213 Массивы реализуют IListинтерфейс, но делают это явно: msdn.microsoft.com/en-us/library/… . (Массивы также реализуют соответствующий общий IList<T>интерфейс.)
— millimoose 07

1
@ sa_ddam213 Нет, договор ToList()всегда копировать. Было бы ужасной идеей, чтобы метод иногда копировал, а иногда нет - это привело бы к довольно сумасшедшим ошибкам с псевдонимом. На самом деле реализация ToList()более-менее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

Если индекс не отсортирован, вам необходимо выполнить итерацию по массиву хотя бы один раз, чтобы найти максимальное значение. Я бы использовал простой 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 one [1] -liner:

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 (не так оптимизирован, как vanilla, но компромисс - меньше кода).
  • Сортировать не нужно.
  • Вычислительная сложность: O (n).
  • Сложность пространства: O (n).

Примечания:

  • Убедитесь, что номер (а не индекс) является первым элементом в кортеже, поскольку сортировка кортежей выполняется путем сравнения элементов кортежа слева направо.

это действительно здорово !!
— floydheld

Следует отметить, что для того, чтобы это сработало, предмет, который нужно увеличить, должен быть первым
— Caius Jard

Что вы имеете в виду @CaiusJard? Как показано в тестовом примере, максимальный элемент был найден правильно и был последним.
— Lesair Valmont

Например, сначала в кортеже anArray.Select((n, i) => ( Index: i, Number: n)).Max()находит максимальный индекс, а не максимальное число из-за способа сравнения кортежей (элемент 1 является наиболее значимым и т. Д.)
— Кай Джард

Достаточно справедливо @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);

Но вам действительно стоит написать явный forlop, если вы заботитесь о производительности.


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

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(без операции)

В конце операции у вас есть индекс, по которому должен быть найден максимум. По логике, максимальное значение равноa[mi]

Я не мог понять, как «найти max и index of max» действительно нужно для отслеживания максимального значения, учитывая, что если у вас есть массив, и вы знаете индекс максимального значения, фактическое значение максимального значения это тривиальный случай использования индекса для индексации массива.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.