C #에서 가장 높은 배열 값 및 인덱스 찾기


92

그래서 정렬되지 않은 숫자 배열이 int[] anArray = { 1, 5, 2, 7 };있고 배열 에서 가장 큰 값인 7과 3의 값과 인덱스를 모두 가져와야합니다. 어떻게해야합니까?


지금까지 Max () 메서드를 사용하려고 시도한 다음 이진 검색 메서드를 사용하여 해당 최대 값의 인덱스를 가져 왔지만 배열이 정렬되지 않으면 작동하지 않으므로 음수를 주려고 시도했을 때 사용할 수 없습니다.
Edmund Rojas 2012

@EdmundRojas 바이너리 검색을 사용할 필요가 없습니다. 평범한 선형 검색은 정렬되지 않은 목록에 대해 잘 작동합니다.
millimoose

답변:


144

이것은 가장 매력적인 방법은 아니지만 작동합니다.

(필수 using System.Linq;)

 int maxValue = anArray.Max();
 int maxIndex = anArray.ToList().IndexOf(maxValue);

11
코딩 시간을 많이 절약 할 수 있지만 컬렉션을 두 번 확인하게됩니다.
Garo Yeriazarian 2012

11
.ToList(), 배열이 명시 적으로 구현할 필요도 없습니다IList
millimoose

@GaroYeriazarian 선형 복잡성이 사용 사례에 비해 너무 많은 경우 상수 계수를 1/3로 줄이는 것 이상을 줄여야 할 것입니다. (분명히 무시할만한 최적화는 아닙니다.)
millimoose

1
@ sa_ddam213 배열은 IList인터페이스를 구현 하지만 명시 적으로 구현합니다 : msdn.microsoft.com/en-us/library/… . (배열은 해당하는 일반 IList<T>인터페이스 도 구현합니다 .)
millimoose

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);

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 이상이라고 가정)의 배열 값 으로 초기화 하고 0 으로 초기화 하고 index에서 for 루프를 시작하여 반복 하나를 저장할 수 i = 1있습니다.
존 슈나이더

14

필수 LINQ one [1] -liner :

var max = anArray.Select((value, index) => new {value, index})
                 .OrderByDescending(vi => vi.value)
                 .First();

(정렬은 아마도 다른 솔루션에 비해 성능 저하 일 것입니다.)

[1] : 주어진 값 "1"에 대해.


14
이 솔루션을 추가하는 것은 기껏해야 O (nlogn) 복잡성입니다. 정렬되지 않은 배열의 경우 최대 값을 O (n) 시간 내에 얻을 수 있습니다.
dopplesoldner 2014-06-18

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를 사용합니다 (바닐라만큼 최적화되지는 않았지만 절충안은 코드가 적습니다).
  • 정렬 할 필요가 없습니다.
  • 계산 복잡성 : O (n).
  • 공간 복잡성 : O (n).

비고 :

  • 튜플 정렬은 왼쪽에서 오른쪽으로 튜플 항목을 비교하여 수행되므로 숫자 (인덱스가 아님)가 튜플의 첫 번째 요소인지 확인하십시오.

이거 정말 깔끔 해요 !!
floydheld

이것이 작동하려면 최대 항목이 먼저 있어야 한다는 점을 지적 해야 합니다
Caius Jard

@CaiusJard는 무엇을 의미합니까? 테스트 케이스에 나타낸 바와 같이, 최대 항목이 제대로 발견 하고 그것이 마지막이었다.
Lesair Valmont

예를 들어 튜플에서 먼저 anArray.Select((n, i) => ( Index: i, Number: n)).Max()튜플을 비교하는 방식으로 인해 최대 수 대신 최대 인덱스 를 찾습니다 (item1이 가장 중요 함 등)
Caius Jard

충분히 공평한 @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());

모든 반복에서 anArray.Max ()를 계산하기 때문에 이것은 O (n ^ 2) 솔루션입니다. 대형 어레이의 경우 매우 느려집니다.
Neil

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 int는 그다지 큰 차이는 아니지만 여전히 ...

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

다음은 괜찮은 상수 인자를 가진 O (n) 인 LINQ 솔루션입니다.

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을 작성해야 합니다.


0

그냥 다른 관점 사용 DataTable. 및 DataTable이라는 2 개의 열로 a 를 선언하십시오 . 옵션과 및 값 을 모두 열에 추가하십시오 . 그런 다음 루프를 사용하고 각 배열 항목을 에 행 으로 삽입합니다 . 그런 다음 방법 을 사용 하여 최대 값이있는 행을 선택합니다.indexvalAutoIncrementAutoIncrementSeedAutoIncrementStep1indexforeachdatatableSelect

암호

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
최소 / 최대가 아니라 배열의 첫 번째 값보다 크거나 작은 마지막 값을 반환합니다.
Tomer Wolberg

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;
}


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(no-op)

작업이 끝나면 최대 값을 찾을 인덱스가 있습니다. 논리적으로 최대 값은a[mi]

배열이 있고 최대 값의 인덱스, 최대 값의 실제 값을 알고 있다면 "최대 값 찾기 및 최대 값 찾기"가 최대 값을 추적하는 데 얼마나 필요한지 알 수 없습니다. 인덱스를 사용하여 배열을 인덱싱하는 사소한 경우입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.