12

Tôi chỉ tự hỏi phương pháp tốt nhất cho phép tính đó là gì. Giả sử tôi có một mảng đầu vào của các giá trị và mảng các ranh giới - tôi muốn tính toán/phân bổ tần số phân bổ cho từng phân đoạn trong mảng ranh giới.Cách nhanh nhất để tính toán phân phối tần số cho mảng trong C# là gì?

Ý tưởng hay là sử dụng tìm kiếm nhóm cho điều đó?

Trên thực tế tôi thấy rằng câu hỏi Calculating frequency distribution of a collection with .Net/C#

Nhưng tôi không hiểu làm thế nào để sử dụng xô cho mục đích đó gây ra kích thước của mỗi thùng có thể khác nhau trong hoàn cảnh của tôi.

EDIT: Sau tất cả các cuộc thảo luận tôi có giải pháp vòng lặp bên trong/bên ngoài, nhưng tôi vẫn muốn loại bỏ vòng lặp bên trong bằng từ điển để có hiệu suất O (n) trong trường hợp đó. giá trị vào chỉ mục nhóm. Vì vậy, chúng ta cần một số loại hàm băm với O (1) phức tạp? Có ý tưởng nào để làm nó không không?

+1

Bạn có thể mô tả các mảng ranh giới tốt hơn một chút? Có bất kỳ mối quan hệ nào giữa các ranh giới khác nhau (tức là chúng có liên tiếp) hay chúng hoàn toàn ngẫu nhiên về kích thước và "vị trí"? Tôi giả sử mảng ranh giới hoàn toàn bao gồm phạm vi giá trị có thể - đó là sự thật? Ngoài ra, tôi giả sử không có chồng chéo - phải không? –

+0

nhanh nhất trong ý nghĩa của chữ "O" lớn hoặc theo ý nghĩa của mã nhỏ? Một cách tiếp cận đơn giản sẽ là viết cho mình một hàm Func và sử dụng hàm này với LINQ .GroupBy để nhóm nhóm này thành "Nhóm" - nhưng có thể có cách tính toán nhanh hơn để thực hiện việc này. – Carsten

+0

Có, bạn đã đúng. Các giá trị biên là tăng đơn điệu về giá trị. Chúng không có chồng chéo và bao trùm phạm vi giá trị có thể. Ví dụ: 0, 10, 50, 100, 120. – Andrey

Trả lời

4

Sắp xếp nhóm đã là trường hợp xấu nhất O (n^2), vì vậy tôi chỉ làm một vòng lặp bên trong/bên ngoài đơn giản tại đây. Vì mảng nhóm của bạn nhất thiết phải ngắn hơn mảng đầu vào của bạn, hãy giữ nó trong vòng lặp bên trong. Vì bạn đang sử dụng kích thước nhóm tùy chỉnh, thực sự không có thủ thuật toán học nào có thể loại bỏ vòng lặp bên trong đó.

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

Đây cũng là trường hợp xấu nhất O (n^2) nhưng bạn không thể đánh bại sự đơn giản của mã. Tôi sẽ không lo lắng về việc tối ưu hóa cho đến khi nó trở thành một vấn đề thực sự. Nếu bạn có một mảng nhóm lớn hơn, bạn có thể sử dụng tìm kiếm nhị phân của một số loại. Nhưng, vì các bản phân phối tần số thường là < 100 yếu tố, tôi nghi ngờ bạn sẽ thấy rất nhiều lợi ích hiệu suất thực tế.

+1

Bạn nghĩ gì về việc triển khai BucketizedHashtable như được trình bày trong Java? Hoặc những gì về sắp xếp mảng ở đầu thực hiện, nó có ý nghĩa không? –

+0

Loại bỏ vòng lặp bên trong bằng 'Từ điển ' để có được phân bổ O (n) perf. –

+0

@Hans Ý của bạn là gì? Tôi không thực sự hiểu: ( – Andrey

1

Nếu mảng đầu vào của bạn đại diện cho dữ liệu thế giới thực (với mô hình của nó) và mảng ranh giới là lớn để lặp lại một lần nữa và một lần nữa trong vòng lặp bên trong, bạn có thể xem xét các phương pháp sau đây:

  • Trước hết loại mảng đầu vào của bạn. Nếu bạn làm việc với dữ liệu trong thế giới thực Tôi khuyên bạn nên xem xét Timsort - Wiki cho việc này. Nó cung cấp đảm bảo hiệu suất rất tốt cho một mẫu có thể được nhìn thấy trong dữ liệu trong thế giới thực.

  • Traverse qua mảng được sắp xếp và so sánh nó với giá trị đầu tiên trong mảng ranh giới:

    • Nếu giá trị trong mảng đầu vào là ít sau đó ranh giới - tần số tăng truy cập cho ranh giới này
    • Nếu giá trị trong mảng đầu vào lớn hơn sau đó là ranh giới - đi tới giá trị tiếp theo trong mảng các ranh giới và tăng bộ đếm cho ranh giới mới.

Trong một mã nó có thể trông như thế này:

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

được biểu diễn bằng mảng giá trị. nhưng về sự phức tạp thì sao? như tôi đã hiểu cho Timsort trong trường hợp xấu nhất O (nlogn) + O (n) cho vòng lặp. Tôi nghĩ rằng vòng lặp bên trong/bên ngoài whith tìm kiếm nhị phân nên được tốt hơn? – Andrey

+2

Không hoàn toàn đúng. Điều này sẽ thất bại nếu có một thùng "trống" ở giữa. Nghĩa là, có hai giá trị đầu vào trong mảng được sắp xếp nằm cạnh nhau, nhưng đi vào các nhóm không nằm cạnh nhau. Nhưng điều đó có thể được khắc phục. Tất cả trong tất cả, đây là một ý tưởng rất tốt. Tùy thuộc vào dữ liệu, thậm chí có thể sử dụng Radix Sort, là O (n), mặc dù nó có thể đòi hỏi rất nhiều dữ liệu để làm cho nó đáng giá. Nhưng thời gian chạy tổng thể sẽ là một O sạch (n). –

+0

P.S. Xin lỗi vì đã đăng bài này làm câu trả lời. Nó có nghĩa là một bình luận. –