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

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);
sa_ddam213
источник
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);
asr
источник
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).

Примечания:

  • Убедитесь, что номер (а не индекс) является первым элементом в кортеже, поскольку сортировка кортежей выполняется путем сравнения элементов кортежа слева направо.
Lesair Valmont
источник
это действительно здорово !!
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;
}

Judavi
источник
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» действительно нужно для отслеживания максимального значения, учитывая, что если у вас есть массив, и вы знаете индекс максимального значения, фактическое значение максимального значения это тривиальный случай использования индекса для индексации массива.

Кай Джард
источник