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ć?
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ć?
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);
.ToList()
, tablice jawnie implementowaneIList
IList
interfejs, ale robią to wyraźnie: msdn.microsoft.com/en-us/library/… . (Tablice również implementują odpowiedni IList<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 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 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).
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 od i = 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”.
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:
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}");
}
anArray.Select((n, i) => new { Value = n, Index = i })
.Where(s => s.Value == anArray.Max());
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;
}
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();
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);
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.
Po prostu inna perspektywa DataTable
. Zadeklaruj a DataTable
z 2 kolumnami o nazwie index
i val
. Dodaj AutoIncrement
opcję oraz oba AutoIncrementSeed
i AutoIncrementStep
wartości 1
do index
kolumny. Następnie użyj foreach
pętli i wstaw każdy element tablicy do datatable
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
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);
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;
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;
}
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);
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 przez mi
), którą znaleźliśmy do tej pory, jest mniejsza niż bieżąca pozycja?
mi
, pamiętając i
,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.