Vì vậy, tôi có một mảng số chưa được sắp xếp int[] anArray = { 1, 5, 2, 7 };
và tôi cần lấy cả giá trị và chỉ số của giá trị lớn nhất trong mảng sẽ là 7 và 3, tôi sẽ làm như thế nào?
Vì vậy, tôi có một mảng số chưa được sắp xếp int[] anArray = { 1, 5, 2, 7 };
và tôi cần lấy cả giá trị và chỉ số của giá trị lớn nhất trong mảng sẽ là 7 và 3, tôi sẽ làm như thế nào?
Câu trả lời:
Đây không phải là cách quyến rũ nhất nhưng hiệu quả.
(phải có using System.Linq;
)
int maxValue = anArray.Max();
int maxIndex = anArray.ToList().IndexOf(maxValue);
.ToList()
, mảng triển khai rõ ràngIList
IList
giao diện, nhưng chúng thực hiện một cách rõ ràng: msdn.microsoft.com/en-us/library/… . (Mảng cũng triển khai IList<T>
giao diện chung tương ứng .)
ToList()
là luôn sao chép. Sẽ là một ý tưởng khủng khiếp nếu phương pháp này đôi khi sao chép và đôi khi không - điều này sẽ dẫn đến lỗi răng cưa khá điên rồ. Trong thực tế việc thực hiện ToList()
là nhiều hơn hoặc ít hơnreturn new List(source)
Nếu chỉ mục không được sắp xếp, bạn phải lặp qua mảng ít nhất một lần để tìm giá trị cao nhất. Tôi sẽ sử dụng một for
vòng lặp đơn giản :
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;
}
}
Điều này dài dòng hơn một cái gì đó sử dụng LINQ hoặc các giải pháp một dòng khác, nhưng nó có thể nhanh hơn một chút. Thực sự không có cách nào để thực hiện điều này nhanh hơn O (N).
maxVal
thành giá trị mảng ở chỉ số 0 (giả sử mảng có độ dài ít nhất là 1), index
thành 0 và bắt đầu vòng lặp for tại i = 1
.
LINQ bắt buộc một [1] -liner:
var max = anArray.Select((value, index) => new {value, index})
.OrderByDescending(vi => vi.value)
.First();
(Việc sắp xếp có thể là một hiệu suất vượt trội so với các giải pháp khác.)
[1]: Cho các giá trị đã cho của "một".
Một lớp lót ngắn gọn:
var max = anArray.Select((n, i) => (Number: n, Index: i)).Max();
Trường hợp thử nghiệm:
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.
Đặc trưng:
Nhận xét:
anArray.Select((n, i) => ( Index: i, Number: n)).Max()
tìm chỉ số tối đa thay vì số tối đa do cách so sánh các bộ giá trị (item1 là quan trọng nhất, v.v.)
Đây là hai cách tiếp cận. Bạn có thể muốn thêm xử lý khi mảng trống.
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());
Đầu ra cho mã dưới đây:
00: 00: 00.3279270 - max1 00: 00: 00.2615935 - max2 00: 00: 00.6010360 - max3 (arr.Max ())
Với 100000000 ints trong mảng không có sự khác biệt quá lớn nhưng vẫn ...
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;
}
}
Điều này hoạt động cho tất cả các loại biến ...
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);
Đây là một giải pháp LINQ là O (n) với các hệ số không đổi phù hợp:
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);
Nhưng bạn thực sự nên viết một for
lop rõ ràng nếu bạn quan tâm đến hiệu suất.
Chỉ là một góc nhìn khác bằng cách sử dụng DataTable
. Khai báo a DataTable
với 2 cột được gọi là index
và val
. Thêm một AutoIncrement
tùy chọn và cả hai AutoIncrementSeed
và AutoIncrementStep
các giá trị 1
vào index
cột. Sau đó, sử dụng một foreach
vòng lặp và chèn từng mục mảng vào datatable
dưới dạng một hàng. Sau đó, bằng Select
phương pháp sử dụng , hãy chọn hàng có giá trị lớn nhất.
Mã
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]);
Đầu ra
Max Value = 7, Index = 4
Tìm số lớn nhất và số nhỏ nhất trong mảng:
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);
Nếu bạn biết chỉ mục tối đa truy cập giá trị tối đa là ngay lập tức. Vì vậy, tất cả những gì bạn cần là chỉ số tối đa.
int max=0;
for(int i = 1; i < arr.Length; i++)
if (arr[i] > arr[max]) max = i;
Hãy xem xét những điều sau:
/// <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;
}
Sử dụng:
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);
Điều này có thể được thực hiện với một for
vòng không có thân, nếu chúng ta đang hướng tới chơi gôn;)
//a is the array
int mi = a.Length - 1;
for (int i=-1; ++i<a.Length-1; mi=a[mi]<a[i]?i:mi) ;
Kiểm tra ++i<a.Length-1
bỏ sót kiểm tra chỉ mục cuối cùng. Chúng tôi không bận tâm về điều này nếu chúng tôi thiết lập nó như thể chỉ mục tối đa là chỉ mục cuối cùng để bắt đầu .. Khi vòng lặp chạy cho các phần tử khác, nó sẽ kết thúc và điều này hoặc điều khác là đúng:
mi
mi
và chúng tôi mắc kẹt vớimi
Công việc thực sự được thực hiện bởi các công cụ sửa đổi vòng lặp sau:
a[mi]
tức là mảng được lập chỉ mục bởi mi
) mà chúng tôi tìm thấy cho đến nay có nhỏ hơn mục hiện tại không?
mi
bằng cách ghi nhớ i
,mi
(no-op)Khi kết thúc hoạt động, bạn có chỉ mục mà tại đó giá trị tối đa sẽ được tìm thấy. Về mặt logic thì giá trị tối đa làa[mi]
Tôi không thể hiểu rõ "tìm giá trị tối đa và chỉ mục của giá trị tối đa" thực sự cần thiết như thế nào để theo dõi giá trị tối đa, vì nếu bạn có một mảng và bạn biết chỉ số của giá trị tối đa, giá trị thực của giá trị tối đa là một trường hợp nhỏ khi sử dụng chỉ mục để lập chỉ mục mảng ..