Итак, у меня есть несортированный числовой массив, 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
Вам даже не нужно .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)
Если индекс не отсортирован, вам необходимо выполнить итерацию по массиву хотя бы один раз, чтобы найти максимальное значение. Я бы использовал простой forцикл:
int? maxVal = null; //nullable so this works even if you have all super-low negativesint 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).
Вы можете сэкономить одну итерацию, инициализировав 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();
(Сортировка, вероятно, снижает производительность по сравнению с другими решениями.)
Просто добавить это решение в лучшем случае сложность O (nlogn). Нахождение max может быть получено за время O (n) для несортированного массива.
dopplesoldner
13
Краткое однострочное письмо:
var max = anArray.Select((n, i) => (Number: n, Index: i)).Max();
Прецедент:
var anArray = newint[] { 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).
Примечания:
Убедитесь, что номер (а не индекс) является первым элементом в кортеже, поскольку сортировка кортежей выполняется путем сравнения элементов кортежа слева направо.
Следует отметить, что для того, чтобы это сработало, предмет, который нужно увеличить, должен быть первым
Caius Jard
Что вы имеете в виду @CaiusJard? Как показано в тестовом примере, максимальный элемент был найден правильно и был последним.
Lesair Valmont
Например, сначала в кортеже anArray.Select((n, i) => ( Index: i, Number: n)).Max()находит максимальный индекс, а не максимальное число из-за способа сравнения кортежей (элемент 1 является наиболее значимым и т. Д.)
Кай Джард
Достаточно справедливо @CaiusJard, я добавил замечание, чтобы указать на это. Спасибо.
Lesair Valmont,
3
Вот два подхода. Вы можете захотеть добавить обработку, когда массив пуст.
publicstaticvoidFindMax()
{
// 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 understandint[] 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}");
}
publicstaticvoidFindMax2()
{
// Advantages: // * Near-optimal performanceint[] 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 conditionfor (int i = 0; i < array.Length; i++)
{
intvalue = array[i];
if (value > maxInt)
{
maxInt = value;
maxIndex = i;
}
}
Console.WriteLine($"Maximum int {maxInt} is found at index {maxIndex}");
}
С 100000000 ints в массиве не очень большая разница, но все же ...
classProgram
{
staticvoidMain(string[] args)
{
int[] arr = newint[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());
}
privatestaticintGetMaxPartialIterate(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;
}
privatestaticintGetMaxFullIterate(int[] arr)
{
var max = arr[0];
for (int i = 0; i < arr.Length; i++)
{
if (arr[i] > max)
{
max = arr[i];
}
}
return max;
}
publicstaticclassArrayExtensions
{
publicstaticintMaxIndexOf<T>(this T[] input)
{
var max = input.Max();
int index = Array.IndexOf(input, max);
return index;
}
}
Это работает для всех типов переменных ...
var array = newint[]{1, 2, 4, 10, 0, 2};
var index = array.MaxIndexOf();
var array = newdouble[]{1.0, 2.0, 4.0, 10.0, 0.0, 2.0};
var index = array.MaxIndexOf();
Просто другая перспектива использования 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]);
int[] arr = newint[] {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);
Это версия C #. Он основан на идее сортировки массива.
publicintsolution(int[] A)
{
// write your code in C# 6.0 with .NET 4.5 (Mono)
Array.Sort(A);
var max = A.Max();
if(max < 0)
return1;
elsefor (int i = 1; i < max; i++)
{
if(!A.Contains(i)) {
return i;
}
}
return max + 1;
}
///<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>publicstaticintMaxAt(int[] arr, outint 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(newint[]{1,2,7,3,4,5,6}, out at);
Console.WriteLine("Max: {0}, found at: {1}", m, at);
Это можно сделать с помощью бестелесной forпетли, если мы идем в гольф;)
//a is the arrayint 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» действительно нужно для отслеживания максимального значения, учитывая, что если у вас есть массив, и вы знаете индекс максимального значения, фактическое значение максимального значения это тривиальный случай использования индекса для индексации массива.
Ответы:
Это не самый гламурный способ, но работает.
(должно быть
using System.Linq;
)int maxValue = anArray.Max(); int maxIndex = anArray.ToList().IndexOf(maxValue);
источник
.ToList()
явно реализовывать массивыIList
IList
интерфейс, но делают это явно: msdn.microsoft.com/en-us/library/… . (Массивы также реализуют соответствующий общийIList<T>
интерфейс.)ToList()
всегда копировать. Было бы ужасной идеей, чтобы метод иногда копировал, а иногда нет - это привело бы к довольно сумасшедшим ошибкам с псевдонимом. На самом деле реализацияToList()
более-менееreturn new List(source)
int[] anArray = { 1, 5, 2, 7 }; // Finding max int m = anArray.Max(); // Positioning max int p = Array.IndexOf(anArray, m);
источник
Если индекс не отсортирован, вам необходимо выполнить итерацию по массиву хотя бы один раз, чтобы найти максимальное значение. Я бы использовал простой
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).
источник
maxVal
значение массива с индексом 0 (при условии, что длина массива не менее 1),index
до 0 и запустив цикл for сi = 1
.Обязательный LINQ one [1] -liner:
var max = anArray.Select((value, index) => new {value, index}) .OrderByDescending(vi => vi.value) .First();
(Сортировка, вероятно, снижает производительность по сравнению с другими решениями.)
[1]: Для заданных значений «один».
источник
Краткое однострочное письмо:
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.
Особенности:
Примечания:
источник
anArray.Select((n, i) => ( Index: i, Number: n)).Max()
находит максимальный индекс, а не максимальное число из-за способа сравнения кортежей (элемент 1 является наиболее значимым и т. Д.)Вот два подхода. Вы можете захотеть добавить обработку, когда массив пуст.
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}"); }
источник
anArray.Select((n, i) => new { Value = n, Index = i }) .Where(s => s.Value == anArray.Max());
источник
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);
источник
Вывод для кода ниже:
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; }
источник
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();
источник
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); }
источник
int[] Data= { 1, 212, 333,2,12,3311,122,23 }; int large = Data.Max(); Console.WriteLine(large);
источник
Вот решение 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
lop, если вы заботитесь о производительности.источник
Просто другая перспектива использования
DataTable
. Объявите aDataTable
с двумя столбцами, называемыми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
Найдите демо здесь
источник
Находит наибольшее и наименьшее число в массиве:
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);
источник
Если вы знаете, что максимальный индекс, доступ к максимальному значению происходит немедленно. Итак, все, что вам нужно, это максимальный индекс.
int max=0; for(int i = 1; i < arr.Length; i++) if (arr[i] > arr[max]) max = i;
источник
Это версия 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; }
источник
Учтите следующее:
/// <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);
источник
Это можно сделать с помощью бестелесной
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» действительно нужно для отслеживания максимального значения, учитывая, что если у вас есть массив, и вы знаете индекс максимального значения, фактическое значение максимального значения это тривиальный случай использования индекса для индексации массива.
источник