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


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.