12

나는 그 계산을 위해 가장 좋은 방법이 무엇인지 궁금 할뿐입니다. 입력 배열의 값과 경계 배열이 있다고 가정합니다. 경계 배열의 각 세그먼트에 대한 빈도 분포를 계산/버킷 화하려고합니다.C#에서 배열의 도수 분포를 계산하는 가장 빠른 방법은 무엇입니까?

버켓 검색을 사용하는 것이 좋습니까?

사실 나는 그 질문에 Calculating frequency distribution of a collection with .Net/C#

을 발견하지만 각 버킷의 크기가 내 상황에서 다를 수 있습니다 원인이 그 목적 버킷을 사용하는 방법을 이해하지 않습니다.

편집 : 내부/외부 루프 솔루션을 가지고 있지만, 내가 입력을 해시 할 필요가 제대로 이해하면 아직도 내가,이 경우 O (n)의 퍼포먼스를 얻기 위해 사전에 내부 루프를 제거하려는 모든 토론 후 값을 버킷 인덱스로 변환합니다. 그래서 우리는 O (1) 복잡성을 지닌 일종의 해시 함수가 필요합니까? 어떤 아이디어로 그것을 할 수 있습니까?

+1

당신은 조금 더 경계 배열을 설명 할 수 있습니까? 다양한 경계 사이에 어떤 관계가 있습니까? (즉 순차적입니까?) 크기 나 위치가 완전히 무작위입니까? 경계 배열이 가능한 값의 범위를 완전히 커버한다고 가정합니다. 사실입니까? 또한 중복이 없다고 가정합니다. 맞습니까? –

+0

큰 "O"또는 작은 코드의 의미에서 가장 빠릅니까? 간단한 접근법은 자신에게 Func 함수를 작성하고이를 Linqs .GroupBy와 함께 사용하여 이것을 "Bucket"으로 그룹화 할 수 있습니다. 그러나이를 수행하는 계산 방법이 더 빠를 수도 있습니다. – Carsten

+0

네, 맞습니다. 경계 값은 값이 단조롭게 증가합니다. 그들은 겹치지 않으며 가능한 값의 범위를 커버합니다. 예 : 0, 10, 50, 100, 120. – Andrey

답변

4

버킷 정렬은 이미 O (n^2) 최악의 경우이므로 여기에서 간단한 내부/외부 루프를 수행합니다. 버킷 배열은 입력 배열보다 반드시 짧아야하므로 내부 루프에 보관하십시오. 사용자 정의 버킷 크기를 사용하기 때문에 실제로 내부 루프를 제거 할 수있는 수학적인 트릭이 없습니다.

int[] freq = new int[buckets.length - 1]; 
foreach(int d in input) 
{ 
    for(int i = 0; i < buckets.length - 1; i++) 
    { 
     if(d >= buckets[i] && d < buckets[i+1]) 
     { 
      freq[i]++; 
      break; 
     } 
    } 
} 

최악의 경우이지만 코드 단순성을 이길 수는 없습니다. 나는 그것이 진짜 문제가 될 때까지 최적화에 대해 걱정하지 않을 것이다. 더 큰 버킷 배열을 가지고 있다면, 어떤 종류의 바이너리 검색을 사용할 수 있습니다. 그러나 빈도 분포는 일반적으로 <100 요소이므로 실제 성능에 많은 이점이 있을지는 의문입니다.

+1

Java에서 제공되는 BucketizedHashtable 구현에 대해 어떻게 생각하십니까? 또는 실행 시작시 배열 정렬은 어떨까요? –

+0

'Dictionary '를 사용하여 안쪽 루프를 제거하여 상환 된 O (n) perf를 얻습니다. –

+0

@ 한스 무슨 소리 야? 난 이해가 안 돼요 : ( – Andrey

1

사용자의 입력 배열은 (그 패턴) 실제 데이터를 나타내며 경계의 배열은 또 다시 반복하는 내부 루프에서 다음과 같은 방법을 고려할 수 많은 경우 : 모든 종류의

  • 먼저 귀하의 입력 배열. 실제 데이터로 작업하는 경우 나는 이것을 Timsort - Wiki으로 생각하는 것이 좋습니다. 은 실제 데이터에서 볼 수있는 패턴에 대해 매우 우수한 성능 보장을 제공합니다. 정렬 된 배열을

  • 트래버스와 경계의 배열에서 첫 번째 값과 비교 :

    • 입력 배열의 값이 경계 후 ​​작은 경우

      -이 경계에 대한 증분 주파수 카운터
    • 경우 값 입력 배열이 더 큰 경우 경계 - 경계 배열의 다음 값으로 이동하고 새 경계에 대해 카운터를 증가시킵니다. 그것은 다음과 같이 할 수있는 코드에서

는 :

Timsort(myArray); 
int boundPos; 
boundaries = GetBoundaries(); //assume the boundaries is a Dictionary<int,int>() 

for (int i = 0; i<myArray.Lenght; i++) { 
    if (myArray[i]<boundaries[boundPos]) { 
    boundaries[boubdPos]++; 
    } 
    else { 
    boundPos++; 
    boundaries[boubdPos]++; 
    } 
} 
+1

경계는 값의 배열로 표시됩니다. 그러나 복잡성은 어떨까요? 내가 Timsort를 최악의 경우 O (nlogn) + O (n) 루핑으로 이해함에 따라. 내부/외부 루프 whith 바이너리 검색이 더 좋을 것이라고 생각합니까? – Andrey

+2

맞지 않습니다. 중간에 "빈"버킷이 있으면이 작업은 실패합니다. 즉, 정렬 된 배열에는 서로 인접한 두 개의 입력 값이 있지만 서로 옆에 있지 않은 버킷으로 들어갑니다. 하지만 수정 될 수 있습니다. 대체적으로 이것은 매우 좋은 아이디어입니다. 데이터에 따라 O (n) 인 기수 정렬을 사용할 수도 있지만 보람있는 데이터를 만들기 위해서는 많은 양이 필요할 수 있습니다. 하지만 전반적인 런타임은 깨끗한 O (n)이 될 것입니다. –

+0

P. 답변으로이 텍스트를 게시하는 것에 대해 유감스럽게 생각합니다. 그것은 논평하기위한 것이었다. –