Mam więc nieposortowaną tablicę liczbową int[] anArray = { 1, 5, 2, 7 };i muszę uzyskać zarówno wartość, jak i indeks największej wartości w tablicy, która będzie równa 7 i 3, jak mam to zrobić?
Do tej pory próbowałem użyć metody Max (), a następnie użyć metody wyszukiwania binarnego, aby uzyskać indeks tej wartości maksymalnej, ale to nie działa, chyba że tablica jest posortowana, więc nie mogę jej użyć, kiedy próbowałem, że dała mi liczby ujemne
Edmund Rojas
@EdmundRojas Nie musisz używać wyszukiwania binarnego. Zwykłe wyszukiwanie liniowe działa dobrze w przypadku list nieposortowanych.
millimoose
Odpowiedzi:
144
To nie jest najbardziej efektowny sposób, ale działa.
(musi mieć using System.Linq;)
int maxValue = anArray.Max();
int maxIndex = anArray.ToList().IndexOf(maxValue);
Oszczędzasz dużo czasu na kodowaniu, ale w końcu dwukrotnie przejrzysz kolekcję.
Garo Yeriazarian
11
Nie potrzebujesz nawet .ToList(), tablice jawnie implementowaneIList
millimoose
@GaroYeriazarian Jeśli złożoność liniowa jest zbyt duża dla twojego przypadku użycia, prawdopodobnie będziesz potrzebować więcej niż tylko zredukować stały współczynnik o jedną trzecią. (Chociaż oczywiście nie jest to pomijalna optymalizacja.)
millimoose
1
@ sa_ddam213 Tablice implementują IListinterfejs, ale robią to wyraźnie: msdn.microsoft.com/en-us/library/… . (Tablice również implementują odpowiedni IList<T>interfejs ogólny .)
millimoose
1
@ sa_ddam213 Nie, umowa ToList()dotyczy zawsze kopiowania. Byłoby okropnym pomysłem, gdyby metoda czasami się kopiowała, a czasami nie - prowadziłoby to do całkiem szalonych błędów związanych z aliasowaniem. W rzeczywistości realizacja ToList()jest mniej więcejreturn new List(source)
Jeśli indeks nie jest posortowany, musisz co najmniej raz powtórzyć tablicę, aby znaleźć najwyższą wartość. Użyłbym prostej forpętli:
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;
}
}
Jest to bardziej szczegółowe niż coś przy użyciu LINQ lub innych rozwiązań jednowierszowych, ale prawdopodobnie jest trochę szybsze. Naprawdę nie ma sposobu, aby zrobić to szybciej niż O (N).
Możesz zapisać jedną iterację, inicjując maxValwartość tablicy pod indeksem 0 (zakładając, że tablica ma długość co najmniej 1), indexdo 0 i rozpoczynając pętlę for od i = 1.
Jon Schneider
14
Obowiązkowa LINQ one [1] -liner:
var max = anArray.Select((value, index) => new {value, index})
.OrderByDescending(vi => vi.value)
.First();
(Sortowanie jest prawdopodobnie lepszym rozwiązaniem niż inne rozwiązania).
Samo dodanie tego rozwiązania to w najlepszym przypadku złożoność O (nlogn). Znalezienie max można uzyskać w czasie O (n) dla nieposortowanej tablicy.
dopplesoldner
13
Zwięzły, jednolinijkowy tekst:
var max = anArray.Select((n, i) => (Number: n, Index: i)).Max();
Przypadek testowy:
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.
Cechy:
Używa Linq (nie tak zoptymalizowany jak wanilia, ale kompromisem jest mniej kodu).
Nie trzeba sortować.
Złożoność obliczeniowa: O (n).
Złożoność przestrzeni: O (n).
Uwagi:
Upewnij się, że liczba (a nie indeks) jest pierwszym elementem krotki, ponieważ sortowanie krotek odbywa się poprzez porównywanie elementów krotki od lewej do prawej.
Należy zauważyć, że aby to zadziałało, element maksymalny musi być pierwszy
Caius Jard
Co masz na myśli @CaiusJard? Jak pokazano w przypadku testowym, maksymalna pozycja została poprawnie znaleziona i była ostatnia.
Lesair Valmont
Na przykład jako pierwsza w krotce anArray.Select((n, i) => ( Index: i, Number: n)).Max()znajduje indeks maksymalny zamiast maksymalnej liczby ze względu na sposób porównywania krotek (element1 jest najbardziej znaczący itp.)
Caius Jard
W porządku @CaiusJard, dodałem uwagę, aby to podkreślić. Dzięki.
Lesair Valmont
3
Oto dwa podejścia. Możesz chcieć dodać obsługę, gdy tablica jest pusta.
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}");
}
Przy 100000000 int w tablicy niezbyt duża różnica, ale nadal ...
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;
}
}
Działa to dla wszystkich typów zmiennych ...
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();
Po prostu inna perspektywa DataTable. Zadeklaruj a DataTablez 2 kolumnami o nazwie indexi val. Dodaj AutoIncrementopcję oraz oba AutoIncrementSeedi AutoIncrementStepwartości 1do indexkolumny. Następnie użyj foreachpętli i wstaw każdy element tablicy do datatablewiersza. Następnie za pomocą Selectmetody wybierz wiersz o maksymalnej wartości.
Kod
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]);
Znajduje największą i najmniejszą liczbę w tablicy:
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);
To jest wersja C #. Opiera się na pomyśle sortowania tablicy.
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;
}
Stosowanie:
int m, at;
m = MaxAt(newint[]{1,2,7,3,4,5,6}, out at);
Console.WriteLine("Max: {0}, found at: {1}", m, at);
Można to zrobić za pomocą bezcielesnej forpętli, jeśli zmierzamy w stronę golfa;)
//a is the arrayint mi = a.Length - 1;
for (int i=-1; ++i<a.Length-1; mi=a[mi]<a[i]?i:mi) ;
Sprawdzenie ++i<a.Length-1pomija sprawdzanie ostatniego indeksu. Nie przeszkadza nam to, jeśli ustawimy go tak, jakby indeks maksymalny był ostatnim indeksem, od którego zaczyna się. Gdy pętla zostanie uruchomiona dla innych elementów, zakończy się i jedna lub druga rzecz jest prawdą:
znaleźliśmy nową wartość maksymalną, a tym samym nowy indeks maksymalny mi
ostatni indeks był przez cały czas wartością maksymalną, więc nie znaleźliśmy nowego mii utknęliśmy z początkiemmi
Prawdziwa praca jest wykonywana przez modyfikatory post-loop:
czy maksymalna wartość ( a[mi]tj. tablica indeksowana przez mi), którą znaleźliśmy do tej pory, jest mniejsza niż bieżąca pozycja?
tak, a następnie zapisz nowy mi, pamiętając i,
nie, potem zapisz istniejący mi(no-op)
Pod koniec operacji masz indeks, na którym znajduje się maksimum. Logicznie więc maksymalna wartość toa[mi]
Nie mogłem do końca zrozumieć, dlaczego funkcja „znajdź maksimum i indeks maksimum” była naprawdę potrzebna do śledzenia wartości maksymalnej, biorąc pod uwagę, że jeśli masz tablicę i znasz indeks wartości maksymalnej, rzeczywista wartość wartości maksymalnej to trywialny przypadek użycia indeksu do indeksowania tablicy.
Odpowiedzi:
To nie jest najbardziej efektowny sposób, ale działa.
(musi mieć
using System.Linq;
)int maxValue = anArray.Max(); int maxIndex = anArray.ToList().IndexOf(maxValue);
źródło
.ToList()
, tablice jawnie implementowaneIList
IList
interfejs, ale robią to wyraźnie: msdn.microsoft.com/en-us/library/… . (Tablice również implementują odpowiedniIList<T>
interfejs ogólny .)ToList()
dotyczy zawsze kopiowania. Byłoby okropnym pomysłem, gdyby metoda czasami się kopiowała, a czasami nie - prowadziłoby to do całkiem szalonych błędów związanych z aliasowaniem. W rzeczywistości realizacjaToList()
jest mniej więcejreturn new List(source)
int[] anArray = { 1, 5, 2, 7 }; // Finding max int m = anArray.Max(); // Positioning max int p = Array.IndexOf(anArray, m);
źródło
Jeśli indeks nie jest posortowany, musisz co najmniej raz powtórzyć tablicę, aby znaleźć najwyższą wartość. Użyłbym prostej
for
pętli: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; } }
Jest to bardziej szczegółowe niż coś przy użyciu LINQ lub innych rozwiązań jednowierszowych, ale prawdopodobnie jest trochę szybsze. Naprawdę nie ma sposobu, aby zrobić to szybciej niż O (N).
źródło
maxVal
wartość tablicy pod indeksem 0 (zakładając, że tablica ma długość co najmniej 1),index
do 0 i rozpoczynając pętlę for odi = 1
.Obowiązkowa LINQ one [1] -liner:
var max = anArray.Select((value, index) => new {value, index}) .OrderByDescending(vi => vi.value) .First();
(Sortowanie jest prawdopodobnie lepszym rozwiązaniem niż inne rozwiązania).
[1]: Dla podanych wartości „jeden”.
źródło
Zwięzły, jednolinijkowy tekst:
var max = anArray.Select((n, i) => (Number: n, Index: i)).Max();
Przypadek testowy:
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.
Cechy:
Uwagi:
źródło
anArray.Select((n, i) => ( Index: i, Number: n)).Max()
znajduje indeks maksymalny zamiast maksymalnej liczby ze względu na sposób porównywania krotek (element1 jest najbardziej znaczący itp.)Oto dwa podejścia. Możesz chcieć dodać obsługę, gdy tablica jest pusta.
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}"); }
źródło
anArray.Select((n, i) => new { Value = n, Index = i }) .Where(s => s.Value == anArray.Max());
źródło
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);
źródło
Dane wyjściowe dla kodu poniżej:
00: 00: 00.3279270 - max1 00: 00: 00.2615935 - max2 00: 00: 00.6010360 - max3 (arr.Max ())
Przy 100000000 int w tablicy niezbyt duża różnica, ale nadal ...
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; }
źródło
public static class ArrayExtensions { public static int MaxIndexOf<T>(this T[] input) { var max = input.Max(); int index = Array.IndexOf(input, max); return index; } }
Działa to dla wszystkich typów zmiennych ...
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();
źródło
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); }
źródło
int[] Data= { 1, 212, 333,2,12,3311,122,23 }; int large = Data.Max(); Console.WriteLine(large);
źródło
Oto rozwiązanie LINQ, które jest O (n) z przyzwoitymi współczynnikami stałymi:
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);
Ale naprawdę powinieneś napisać wyraźny
for
lop, jeśli zależy ci na wydajności.źródło
Po prostu inna perspektywa
DataTable
. Zadeklaruj aDataTable
z 2 kolumnami o nazwieindex
ival
. DodajAutoIncrement
opcję oraz obaAutoIncrementSeed
iAutoIncrementStep
wartości1
doindex
kolumny. Następnie użyjforeach
pętli i wstaw każdy element tablicy dodatatable
wiersza. Następnie za pomocąSelect
metody wybierz wiersz o maksymalnej wartości.Kod
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]);
Wynik
Max Value = 7, Index = 4
Znajdź tutaj demo
źródło
Znajduje największą i najmniejszą liczbę w tablicy:
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);
źródło
Jeśli wiesz, że indeks maksymalny, dostęp do wartości maksymalnej jest natychmiastowy. Więc wszystko czego potrzebujesz to max index.
int max=0; for(int i = 1; i < arr.Length; i++) if (arr[i] > arr[max]) max = i;
źródło
To jest wersja C #. Opiera się na pomyśle sortowania tablicy.
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; }
źródło
Rozważ następujące kwestie:
/// <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; }
Stosowanie:
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);
źródło
Można to zrobić za pomocą bezcielesnej
for
pętli, jeśli zmierzamy w stronę golfa;)//a is the array int mi = a.Length - 1; for (int i=-1; ++i<a.Length-1; mi=a[mi]<a[i]?i:mi) ;
Sprawdzenie
++i<a.Length-1
pomija sprawdzanie ostatniego indeksu. Nie przeszkadza nam to, jeśli ustawimy go tak, jakby indeks maksymalny był ostatnim indeksem, od którego zaczyna się. Gdy pętla zostanie uruchomiona dla innych elementów, zakończy się i jedna lub druga rzecz jest prawdą:mi
mi
i utknęliśmy z początkiemmi
Prawdziwa praca jest wykonywana przez modyfikatory post-loop:
a[mi]
tj. tablica indeksowana przezmi
), którą znaleźliśmy do tej pory, jest mniejsza niż bieżąca pozycja?mi
, pamiętająci
,mi
(no-op)Pod koniec operacji masz indeks, na którym znajduje się maksimum. Logicznie więc maksymalna wartość to
a[mi]
Nie mogłem do końca zrozumieć, dlaczego funkcja „znajdź maksimum i indeks maksimum” była naprawdę potrzebna do śledzenia wartości maksymalnej, biorąc pod uwagę, że jeśli masz tablicę i znasz indeks wartości maksymalnej, rzeczywista wartość wartości maksymalnej to trywialny przypadek użycia indeksu do indeksowania tablicy.
źródło