Tính trung vị của một tỷ số


127

Nếu bạn có một tỷ số và một trăm máy tính, cách tốt nhất để xác định trung vị của các số này là gì?

Một giải pháp mà tôi có là:

  • Chia bộ bằng nhau giữa các máy tính.
  • Sắp xếp chúng.
  • Tìm trung vị cho mỗi bộ.
  • Sắp xếp các bộ trên trung vị.
  • Hợp nhất hai bộ tại một thời điểm từ trung bình thấp nhất đến trung bình cao nhất.

Nếu m1 < m2 < m3 ...trước tiên chúng ta đã hợp nhất Set1Set2trong tập kết quả, chúng ta có thể loại bỏ tất cả các số thấp hơn trung vị của Set12(đã hợp nhất). Vì vậy, tại bất kỳ thời điểm nào chúng ta có bộ kích thước bằng nhau. Bằng cách này, điều này không thể được thực hiện theo cách song song. Có ý kiến ​​gì không?


3
@John Boker: thực sự vấn đề bao gồm hai bài toán con: 1) sắp xếp danh sách và 2) lấy phần tử với chỉ số 5'000'000'000. Tôi hầu như không tin rằng những con số được sắp xếp.
La Mã

3
@Roman: vấn đề không cần bao gồm hai biểu tượng con bạn mô tả, ví dụ quickselect. Nhưng quickselect không song song, ít nhất là không tầm thường. Và tất nhiên, bạn đúng rằng nếu các số được sắp xếp trước thì đó là một câu hỏi khá vô nghĩa.
Steve Jessop

5
@fmsf: Tôi không nghĩ bất kỳ quốc gia nói tiếng Anh nào sử dụng hàng tỷ tiếng Anh dài cho bất kỳ mục đích chính thức nào. Ví dụ ở đây tại Vương quốc Anh, chúng tôi đã ngừng sử dụng nó vào năm 1974. Tôi sẽ coi việc sử dụng "tỷ" có nghĩa là một triệu triệu, trong tiếng Anh là một câu hỏi lừa đảo, không phải là "tỷ tỷ thực sự". Tất nhiên trong tiếng Pháp nó sẽ là một vấn đề hoàn toàn khác, nhưng câu hỏi không phải là tiếng Pháp.
Steve Jessop

5
Bạn không cần phải sắp xếp! vi.wikipedia.org/wiki/ từ
glebm

2
1 tỷ số chỉ là một vài gigabyte dữ liệu, bạn không cần nhiều PC cũng như các thuật toán phức tạp để giải quyết công việc này. Đừng quá phức tạp.
dùng626528

Câu trả lời:


54

Ah, bộ não của tôi vừa mới khởi động, tôi có một gợi ý hợp lý bây giờ. Có lẽ đã quá muộn nếu đây là một cuộc phỏng vấn, nhưng đừng bận tâm:

Máy 1 sẽ được gọi là "máy điều khiển" và để tranh luận, nó sẽ bắt đầu với tất cả dữ liệu và gửi nó bằng bưu kiện cho 99 máy khác, hoặc nếu không thì dữ liệu bắt đầu phân bổ đều giữa các máy và nó gửi 1/99 dữ liệu của nó cho từng người khác. Các phân vùng không phải bằng nhau, chỉ cần đóng.

Mỗi máy khác sắp xếp dữ liệu của nó và thực hiện theo cách ưu tiên tìm các giá trị thấp hơn trước. Vì vậy, ví dụ quicksort, luôn sắp xếp phần dưới của phân vùng trước [*]. Nó ghi dữ liệu của nó trở lại máy điều khiển theo thứ tự tăng ngay khi có thể (sử dụng IO không đồng bộ để tiếp tục sắp xếp và có thể với Nagle trên: thử nghiệm một chút).

Máy điều khiển thực hiện hợp nhất 99 chiều trên dữ liệu khi nó đến, nhưng loại bỏ dữ liệu đã hợp nhất, chỉ giữ số lượng giá trị mà nó đã thấy. Nó tính toán trung vị là giá trị trung bình của 1/2 tỷ và 1/2 tỷ cộng với các giá trị oneth.

Điều này bị vấn đề "chậm nhất trong đàn". Thuật toán không thể hoàn thành cho đến khi mọi giá trị nhỏ hơn giá trị trung bình được gửi bởi một máy phân loại. Có một cơ hội hợp lý rằng một giá trị như vậy sẽ khá cao trong phạm vi dữ liệu của nó. Vì vậy, khi phân vùng dữ liệu ban đầu hoàn tất, thời gian chạy ước tính là sự kết hợp thời gian để sắp xếp 1/99 dữ liệu và gửi lại cho máy tính điều khiển và thời gian để điều khiển đọc 1/2 dữ liệu . "Sự kết hợp" nằm ở đâu đó giữa mức tối đa và tổng của những khoảng thời gian đó, có thể gần với mức tối đa.

Bản năng của tôi là để gửi dữ liệu qua mạng nhanh hơn so với việc sắp xếp nó (chứ đừng nói là chọn trung vị), nó cần phải là một mạng nhanh khá chết tiệt. Có thể là một triển vọng tốt hơn nếu mạng có thể được coi là tức thời, ví dụ nếu bạn có 100 lõi với quyền truy cập tương đương vào RAM chứa dữ liệu.

Vì I / O mạng có khả năng bị ràng buộc, nên có thể có một số thủ thuật bạn có thể chơi, ít nhất là đối với dữ liệu quay trở lại máy điều khiển. Ví dụ: thay vì gửi "1,2,3, .. 100", có lẽ một máy sắp xếp có thể gửi một thông điệp có nghĩa là "100 giá trị nhỏ hơn 101". Sau đó, máy điều khiển có thể thực hiện hợp nhất đã sửa đổi, trong đó nó tìm thấy ít nhất trong tất cả các giá trị hàng đầu đó, sau đó cho tất cả các máy phân loại biết nó là gì, để chúng có thể (a) cho máy biết điều khiển như thế nào nhiều giá trị để "đếm" bên dưới giá trị đó và (b) tiếp tục gửi dữ liệu đã sắp xếp của chúng từ thời điểm đó.

Tổng quát hơn, có lẽ có một trò chơi đoán phản ứng thử thách thông minh mà máy điều khiển có thể chơi với 99 máy phân loại.

Điều này liên quan đến các chuyến đi khứ hồi giữa các máy, tuy nhiên, phiên bản đầu tiên đơn giản hơn của tôi tránh được. Tôi thực sự không biết làm thế nào để ước tính hiệu suất tương đối của họ và vì sự đánh đổi rất phức tạp, tôi tưởng tượng có nhiều giải pháp tốt hơn ngoài đó so với bất cứ điều gì tôi nghĩ về bản thân mình, cho rằng đây là vấn đề thực sự.

[*] Cho phép ngăn xếp có sẵn - sự lựa chọn của bạn về phần nào sẽ làm trước tiên bị hạn chế nếu bạn không có thêm không gian O (N). Nhưng nếu bạn có đủ không gian, bạn có thể chọn và nếu bạn không có đủ không gian, ít nhất bạn có thể sử dụng những gì bạn phải cắt một số góc, bằng cách thực hiện phần nhỏ trước cho một vài phân vùng đầu tiên.


Vui lòng sửa cho tôi nếu tôi sai, tại sao bạn thực hiện hợp nhất 99 chiều trên dữ liệu vì nó chỉ đến để loại bỏ sau này. Thay vào đó là đủ để giữ cho số đếm khi nó đến?
sreeprasad

4
@SREEPRASADGOVINDANKUTTY: bước lặp lại là loại bỏ giá trị nhỏ nhất trong số 99 ứng cử viên và tăng số lượng. Hoàn toàn không sử dụng để chỉ giữ một số lượng tất cả các giá trị đến mà không có bước hợp nhất 99 chiều này. Nếu bạn không so sánh chúng khi chúng đến, bạn sẽ không biết rằng giá trị bạn đang loại bỏ nằm dưới mức trung bình.
Steve Jessop

Nhưng không có khả năng nhỏ là bất kỳ phân vùng nào trong số này chỉ chứa các số cao hơn trung vị và do đó, bất kỳ phân vùng thấp hơn nào nó trả về sẽ cao hơn trung bình, nhưng vì kiểm soát không biết điều này sẽ loại bỏ chúng thấp hơn trung bình và thất bại ...?
Gullydwarf

@Gullydwarf: hợp nhất nhiều cách chỉ loại bỏ giá trị nhỏ nhất trong số 99 giá trị có trong tay, mỗi giá trị là giá trị nhỏ nhất còn lại từ một trong các máy khác. Nếu một trong các phân vùng hoàn toàn lớn hơn trung vị, thì nó sẽ không trở thành ít nhất trong số 99 giá trị đó cho đến khi trung vị đã đi qua (tại thời điểm chúng ta kết thúc). Vì vậy, nó sẽ không bị loại bỏ.
Steve Jessop

52
sort -g numbers | head -n 500000001 | tail -n 2 | dc -e "1 k ? ? + 2 / p"

2
CƯỜI LỚN. Điều đó thực sự có tác dụng hay kẻ giết người OOM sẽ nuke nó trước khi nó hoàn thành? (trên bất kỳ máy tính hợp lý nào)
Isak Savo

5
Nên làm. sort biết cách thực hiện một loại sắp xếp ngoài lõi, vì vậy nó sẽ không hết bộ nhớ.
DrPizza

6
@Zagfai Tôi không nghĩ sẽ mất nhiều thời gian; một tỷ số chỉ có 4 GB cho ints / float 32 bit, 8GB cho ints / bit 64 bit. Không có vẻ thuế rất lớn.
DrPizza

13
Chỉ cần thử trên Intel i5-4200M @ 3.1 GHz (4 lõi). Theo timelệnh được áp dụng cho toàn bộ đường ống, phải mất real=36m24s("thời gian đồng hồ treo tường"), user=113m15s ("thời gian song song", tất cả các lõi được thêm vào). Lệnh dài nhất, vượt xa các lệnh khác sort, ngay cả khi nó luồn vào bốn lõi của tôi ở mức 100%. Tiêu thụ RAM là rất chấp nhận được.
Morgan Todarey Quilling

11
Sau đó chạy ở trên 100 máy tính, vì vậy bạn có thể chắc chắn 100 lần hơn mà kết quả là đúng :)
dos

26

Tôi ghét phải là người thay thế ở đây, nhưng tôi không tin việc sắp xếp là bắt buộc và tôi nghĩ rằng bất kỳ thuật toán nào liên quan đến việc sắp xếp một tỷ / 100 số sẽ bị chậm. Hãy xem xét một thuật toán trên một máy tính.

1) Chọn ngẫu nhiên 1000 giá trị từ tỷ và sử dụng chúng để có ý tưởng phân phối các số, đặc biệt là một phạm vi.

2) Thay vì sắp xếp các giá trị, hãy phân bổ chúng vào các thùng dựa trên phân phối bạn vừa tính. Số lượng xô được chọn để máy tính có thể xử lý chúng một cách hiệu quả, nhưng nếu không thì càng lớn càng thuận tiện. Phạm vi nhóm phải sao cho số lượng giá trị bằng nhau trong mỗi nhóm (điều này không quan trọng đối với thuật toán, nhưng nó giúp hiệu quả. 100.000 thùng có thể phù hợp). Lưu ý số lượng giá trị trong mỗi thùng. Đây là một quá trình O (n).

3) Tìm ra cái xô nào nằm trong khoảng giữa. Điều này có thể được thực hiện bằng cách kiểm tra tổng số trong mỗi nhóm.

4) Tìm trung vị thực tế bằng cách kiểm tra các giá trị trong nhóm đó. Bạn có thể sử dụng sắp xếp ở đây nếu bạn thích, vì bạn chỉ sắp xếp có thể 10.000 số. Nếu số lượng giá trị trong nhóm đó lớn thì bạn có thể sử dụng lại thuật toán này cho đến khi bạn có một số lượng đủ nhỏ để sắp xếp.

Cách tiếp cận này song song hóa tầm thường bằng cách chia các giá trị giữa các máy tính. Mỗi máy tính báo cáo tổng số trong mỗi nhóm cho máy tính 'điều khiển' ở bước 3. Đối với bước 4, mỗi máy tính sẽ gửi các giá trị (được sắp xếp) trong nhóm có liên quan đến máy tính điều khiển (bạn cũng có thể thực hiện song song cả hai thuật toán đó, nhưng nó có lẽ không đáng

Toàn bộ quá trình là O (n), vì cả hai bước 3 và 4 đều không đáng kể, với điều kiện số lượng thùng đủ lớn.


1
Tôi nghĩ rằng đây là một cái gì đó ở giữa trung vị của các trung vị và các thuật toán quickselect. vi.wikipedia.org/wiki/Selection_alacticm
Dimath

Ở bước 4, các thùng có thể không chỉ chứa 10.000. Nó có thể là trường hợp phân phối bị lệch về giữa, trong đó, nó có thể chứa 80% dữ liệu, vẫn còn rất lớn.
ngay

Chỉnh sửa để tính đến điều đó.
DJClayworth

Tôi thích cách tiếp cận này.
Al Kepp

4
Hiệu suất không phải là O (n) trong thuật toán này: bạn có thể có hầu hết các số rơi vào nhóm "trung vị" và nó có thể hoạt động tồi tệ như sắp xếp mọi thứ.
Sklivvz

12

Một tỷ thực sự là một nhiệm vụ khá nhàm chán đối với một máy tính hiện đại. Chúng ta đang nói về số nguyên 4 byte trị giá 4 GB ở đây ... 4 GB ... đó là RAM của một số điện thoại thông minh.

public class Median {
    public static void main(String[] args) {
        long start = System.currentTimeMillis();

        int[] numbers = new int[1_000_000_000];

        System.out.println("created array after " +  (System.currentTimeMillis() - start) + " ms");

        Random rand = new Random();
        for (int i = 0; i < numbers.length; i++) {
            numbers[i] = rand.nextInt();
        }

        System.out.println("initialized array after " + (System.currentTimeMillis() - start) + " ms");

        Arrays.sort(numbers);

        System.out.println("sorted array after " + (System.currentTimeMillis() - start) + " ms");

        if (numbers.length % 2 == 1) {
            System.out.println("median = " + numbers[numbers.length / 2 - 1]);
        } else {
            int m1 = numbers[numbers.length / 2 - 1];
            int m2 = numbers[numbers.length / 2];
            double m = ((long) m1 + m2) / 2.0;
            System.out.println("median = " + new DecimalFormat("#.#").format(m));
        }
}

Đầu ra trên máy của tôi:

created array after 518 ms
initialized array after 10177 ms
sorted array after 102936 ms
median = 19196

Vì vậy, điều này hoàn thành trên máy của tôi trong vòng chưa đầy hai phút (1:43 trong đó 0h10 để tạo số ngẫu nhiên) bằng cách sử dụng một lõi duy nhất và thậm chí nó còn thực hiện một cách đầy đủ. Không có gì lạ mắt thực sự.

Đây chắc chắn là một nhiệm vụ thú vị cho các bộ số lớn hơn. Tôi chỉ muốn đưa ra một quan điểm ở đây: một tỷ là đậu phộng. Vì vậy, hãy suy nghĩ hai lần trước khi bạn bắt đầu ném các giải pháp phức tạp vào các nhiệm vụ đơn giản đáng ngạc nhiên;)


đây là những gì tôi đã nói trong câu trả lời của mình ở đây :-) stackoverflow.com/a/31819222/363437
vidstige

1
@vidstige Tôi thực sự không đọc nó, nhưng bạn nói đúng. câu trả lời của tôi chắc chắn là thực tế hơn, mà mọi người dường như đánh giá cao hơn một chút;)
sfussalanger

Đó không phải là mặc dù trung bình, trung bình là (numbers[numbers.length / 2]+numbers[numbers.length / 2+1])/2nếu numbers.lengthlà chẵn và numbers[numbers.length / 2]chỉ nếu numbers.lengthlà số lẻ.
Sklivvz

@Sklivvz đúng, nhưng nó không đáng chú ý ảnh hưởng đến thời gian cần thiết để tính toán trung vị.
vidstige

1
@Sklivvz bạn dĩ nhiên là đúng. Tôi vừa cập nhật tính toán trung bình. Nó không thay đổi phần còn lại của câu trả lời mặc dù.
sfussalanger

10

Các ước lượng số liệu thống kê theo thứ tự như phần trăm trung bình và 99 có thể được phân phối một cách hiệu quả với các thuật toán như t-tiêu hóa hoặc Q-tiêu hóa .

Sử dụng một trong hai thuật toán, mỗi nút tạo ra một thông báo, đại diện cho phân phối của các giá trị được lưu trữ cục bộ. Các bản tóm tắt được thu thập tại một nút, được hợp nhất (tổng hợp hiệu quả các phân phối) và trung bình hoặc bất kỳ phần trăm nào khác có thể được tra cứu.

Cách tiếp cận này được sử dụng bởi elaticsearch và, có lẽ là BigQuery (đi theo mô tả của hàm QUANTILES).


5

Trung vị cho bộ số này

2, 3, 5, 7, 11, 13, 67, 71, 73, 79, 83, 89, 97

là 67.

Trung vị cho bộ số này

2, 3, 5, 7, 11, 13, 67, 71, 73, 79, 83, 89

là 40

Giả sử câu hỏi là khoảng 1.000.000.000 số nguyên (x) trong đó 0> = x <= 2.147.483.647 và OP đang tìm kiếm (phần tử (499.999.999) + phần tử (500.000.000)) / 2 (nếu các số được sắp xếp). Cũng giả sử rằng tất cả 100 máy tính đều như nhau.

sử dụng máy tính xách tay của tôi và GigE ...

Những gì tôi tìm thấy là máy tính xách tay của tôi có thể sắp xếp 10.000.000 Int32 trong 1,3 giây. Vì vậy, một ước tính sơ bộ sẽ là một tỷ số sắp xếp sẽ mất 100 x 1,3 giây (2 phút 10 giây);).

Ước tính truyền tệp một chiều của tệp 40 MB trên Ethernet gigabit là 0,32 giây. Điều này có nghĩa là các kết quả được sắp xếp từ tất cả các máy tính sẽ được trả về trong khoảng 32 giây (máy tính 99 không nhận được tệp của anh ấy cho đến 30 giây sau khi bắt đầu). Từ đó, không mất nhiều thời gian để loại bỏ các số thấp nhất 499.999.998, thêm 2 số tiếp theo và chia cho 2.


3
Bình luận xuống cử tri? Nó sẽ giúp tôi hiểu làm thế nào tôi có thể làm tốt hơn.
dbasnett

5
Tôi không phải là cử tri xuống cấp, nhưng việc sắp xếp một tỷ số sẽ không mất 100 lần so với sắp xếp 10 triệu, vì trường hợp phức tạp nhất của việc sắp xếp danh sách là O (n log n). Sắp xếp cũng là thứ tự cường độ chậm hơn khi bạn hết bộ nhớ và phải bắt đầu sắp xếp trên đĩa.
Richard Poole

Tôi nghĩ rằng bạn đang đi đúng hướng; Nếu mục tiêu là câu trả lời nhanh nhất có thể một lần, sắp xếp trên nhiều máy có thể là một ý tưởng tốt. Nhưng nếu mục tiêu là thời gian trung bình thấp nhất, thì mỗi máy thực hiện tìm kiếm riêng sẽ có ý nghĩa hơn.
Charlie

Giả sử chúng có cùng một yếu tố (mà có lẽ chúng không phải do vấn đề bộ nhớ) thì a*(1e7)log(1e7) = 1.3sec=> a = 1.6e-9sec => a*(1e9)log(1e9) ~ 167sec, vì vậy ước tính của bạn không bị tắt.
bcorso

Ước tính của bạn là cách quá thô. Đầu tiên, một số thuật toán sắp xếp đi theo o (n ^ 2) trong trường hợp xấu nhất (ví dụ: quicksort thường được sử dụng). Thứ hai, bạn đã chọn một tập dữ liệu thử nghiệm có kích thước tương đương với bộ đệm L2 của bạn. Điều này sai lệch kết quả. Thứ ba, bạn (như nhiều người trả lời khác) cho rằng "số" có nghĩa là "số nguyên". Nó có thể có nghĩa là float, double hoặc binary, có các đặc tính hiệu suất rất khác nhau.
Sklivvz

5

Điều này có thể làm mọi người ngạc nhiên, nhưng nếu các số đó đủ nhỏ để vừa trong 32-bit (hoặc nhỏ hơn) - Chỉ cần thực hiện sắp xếp xô! Chỉ cần 16GB ram cho bất kỳ số lượng int 32 bit nào và chạy trong O (n), sẽ vượt trội hơn bất kỳ hệ thống phân tán nào cho n hợp lý, ví dụ: một tỷ.

Một khi bạn có danh sách được sắp xếp, thật tầm thường để chọn ra trung vị. Trong thực tế, bạn không cần phải xây dựng danh sách đã sắp xếp mà chỉ cần nhìn vào các thùng sẽ làm điều đó.

Một thực hiện đơn giản được hiển thị dưới đây. Chỉ hoạt động đối với số nguyên 16 bit, nhưng việc mở rộng thành 32 bit nên dễ dàng.

#include <stdio.h>
#include <string.h>

int main()
{
    unsigned short buckets[65536];
    int input, n=0, count=0, i;

    // calculate buckets
    memset(buckets, 0, sizeof(buckets));
    while (scanf("%d", &input) != EOF)
    {
        buckets[input & 0xffff]++;
        n++;
    }

    // find median 
    while (count <= n/2)
    {
        count += buckets[i++];
    }

    printf("median: %d\n", i-1);

    return 0;
}

Sử dụng tệp văn bản có một tỷ (10 9 ) số và chạy timenhư vậy

time ./median < billion

mang lại thời gian chạy trên máy của tôi 1m49.293s. Hầu hết thời gian chạy có lẽ là đĩa IO.


Điều này không thực sự trả lời câu hỏi và nó dựa trên các giả định. Ví dụ, bạn thậm chí không biết chúng là số nguyên.
Sklivvz

Bằng cách nào nó không trả lời câu hỏi? Và vâng, câu trả lời của tôi giả sử các số là số nguyên. Tôi đã cố gắng nêu rõ các giả định của mình.
vidstige

Bạn dường như không nói rằng việc có số nguyên là một giả định, cũng như bạn không giải quyết cách sử dụng 100 máy tính mà OP yêu cầu. Bạn có thể tính toán trung vị trên một nút nhưng đó không phải là giải pháp "tốt nhất" trừ khi bạn cho thấy lý do tại sao. Ngoài ra, sắp xếp radix không phải là o (n) nếu số chữ số thay đổi, trong trường hợp này chắc chắn là như vậy, theo en.wikipedia.org/wiki/Radix_sort#Effic , đó là o (n log n)
Sklivvz

Tôi bắt đầu bằng cách nói "nếu số nguyên đủ nhỏ để đặt bên trong số nguyên 32 bit " ... Loại Radix là O (n) cho kích thước từ không đổi w như được mô tả rất rõ ràng trong liên kết bạn đã đăng. Ở đây tôi giả sử kích thước từ không đổi là 32.
vidstige

1
Những gì bạn làm với 99 máy tính khác không liên quan trong câu trả lời này. Bạn có thể xếp chúng lên nhau để tạo thành một kim tự tháp hoặc đốt chúng. Hoặc chỉ cần bỏ qua chúng.
vidstige

3

Thật kỳ lạ, tôi nghĩ rằng nếu bạn có đủ máy tính, bạn nên sắp xếp tốt hơn là sử dụng O(n)các thuật toán tìm trung bình. (Trừ khi các lõi của bạn rất, rất chậm, tuy nhiên, tôi chỉ sử dụng một và sử dụng O(n)thuật toán tìm trung bình cho các số 1e9; tuy nhiên, nếu bạn có 1e12, thì điều đó có thể ít thực tế hơn.)

Dù sao đi nữa, giả sử chúng ta có nhiều hơn các lõi đăng nhập để giải quyết vấn đề này và chúng ta không quan tâm đến việc tiêu thụ năng lượng, chỉ cần nhận được câu trả lời nhanh chóng. Chúng ta hãy giả sử rằng đây là một máy SMP với tất cả dữ liệu đã được tải trong bộ nhớ. (Chẳng hạn, máy 32 lõi của Sun thuộc loại này.)

Một luồng cắt danh sách một cách mù quáng thành các mảnh có kích thước bằng nhau và báo cho các luồng M khác sắp xếp chúng. Những chủ đề cần mẫn làm như vậy, trong (n/M) log (n/M)thời gian. Sau đó, họ trả lại không chỉ trung vị của họ, mà, giả sử, phần trăm thứ 25 và 75 của họ cũng vậy (trường hợp xấu nhất là tốt hơn nếu bạn chọn các số hơi khác nhau). Bây giờ bạn có 4M phạm vi dữ liệu. Sau đó, bạn sắp xếp các phạm vi này và làm việc lên trên danh sách cho đến khi bạn tìm thấy một số sao cho, nếu bạn ném ra mọi phạm vi nhỏ hơn hoặc chứa số đó, bạn sẽ bỏ ra một nửa dữ liệu của mình. Đó là giới hạn dưới của bạn cho trung vị. Làm tương tự cho giới hạn trên. Điều này cần một cái gì đó giống như M log Mthời gian và tất cả các lõi phải chờ nó, vì vậy nó thực sự lãng phíM^2 log Mthời gian tiềm năng. Bây giờ bạn có một chủ đề duy nhất của bạn nói với những người khác ném tất cả dữ liệu ra ngoài phạm vi (bạn nên ném ra khoảng một nửa trên mỗi lượt đi) và lặp lại - đây là một thao tác nhanh chóng vì dữ liệu đã được sắp xếp. Bạn không cần phải lặp lại điều này nhiều log(n/M)lần trước khi lấy dữ liệu còn lại nhanh hơn và sử dụng O(n)công cụ tìm trung bình tiêu chuẩn trên đó.

Vì vậy, tổng số phức tạp là một cái gì đó như O((n/M) log (n/M) + M^2 log M log (n/M)). Do đó, điều này nhanh hơn O(n)sắp xếp trung bình trên một lõi nếu M >> log(n/M)M^3 log M < n, điều này đúng với kịch bản bạn đã mô tả.

Tôi nghĩ rằng đây là một ý tưởng thực sự tồi tệ được đưa ra như thế nào là không hiệu quả, nhưng nó nhanh hơn.


o (n / M log (n / M)), theo nghĩa đen là o (n log n), bởi vì o (n / M log (n / M)) = 1 / M o (n (log n - log M) ) = o (n log n). Bạn thực sự không thể so sánh nó với o (n) như thế, vì "o" về cơ bản có nghĩa là "tỷ lệ thuận với rất lớn n với một số hằng số không xác định". Trừ khi bạn biết các hằng số này bạn không thể so sánh, tuy nhiên với N đủ lớn thì các hằng số không chiếm ưu thế. Đối với các số thấp hơn, tất cả các cược được tắt, o (1) có thể dễ dàng chậm hơn o (n!).
Sklivvz

@Sklivvz - nMlà các biến có thể mở rộng tùy ý, do đó, một biến bao gồm cả hai. Cụ thể, tôi đã quy định rằng M> log n, có nghĩa là nếu bạn quan tâm rằng nó n log nthay vì chỉ n, bạn cũng phải quan tâm M.
Rex Kerr

3

Điều này có thể được thực hiện nhanh hơn thuật toán đã bình chọn (n log n)

- Thuật toán lựa chọn phân phối thống kê đơn hàng - O (n)
Đơn giản hóa vấn đề cho vấn đề ban đầu là tìm số thứ k trong một mảng chưa được sắp xếp.
- Đếm biểu đồ sắp xếp O (n)
Bạn phải giả sử một số thuộc tính về phạm vi của các số - phạm vi có thể vừa trong bộ nhớ không? - Sắp xếp hợp nhất bên ngoài - O (n log n) - được mô tả ở trên
Về cơ bản, bạn sắp xếp các số trên đường chuyền đầu tiên, sau đó tìm trung vị trên đường thứ hai.
- Nếu có bất cứ điều gì được biết về phân phối số thì các thuật toán khác có thể được tạo ra.

Để biết thêm chi tiết và triển khai, hãy xem:
http://www.fusu.us/2013/07/median-in-large-set-across-1000-servers.html


2

Một máy tính là quá đủ để giải quyết vấn đề.

Nhưng hãy giả sử rằng có 100 máy tính. Điều phức tạp duy nhất bạn nên làm là sắp xếp danh sách. Chia nó thành 100 phần, gửi một phần cho mỗi máy tính, để chúng được sắp xếp ở đó và hợp nhất các phần sau đó.

Sau đó lấy số từ giữa danh sách được sắp xếp (nghĩa là với chỉ số 5 000 000 000).


3
Dù sao thì bây giờ đại diện của tôi cũng khá tròn :)
Roman

Hợp nhất là tốt nhất O (n) và bạn có thể tìm thấy trung vị trên một lõi đơn trong O (n), vì vậy điều này dường như tạo ra rất nhiều công việc phụ mà không thu được.
Rex Kerr

2

Nó phụ thuộc vào dữ liệu của bạn. Trường hợp xấu nhất là số lượng phân phối đồng đều.

Trong trường hợp này, bạn có thể tìm thấy trung vị trong thời gian O (N) như trong ví dụ này:

Giả sử số của bạn là 2,7,5,10,1,6,4,4,6,10,4,7,1,8,4,9,9,3,4,3,3 (phạm vi là 1-10) .

Chúng tôi tạo ra 3 thùng: 1-3, 4-7, 8-10. Lưu ý rằng trên và dưới có kích thước bằng nhau.

Chúng tôi điền vào các thùng với các số, đếm số lần rơi trong mỗi số, tối đa và tối thiểu

  • thấp (5): 2,1,1,3,3, tối thiểu 1, tối đa 3
  • giữa (10): 7,5,6,4,4,6,4,4,4,4, tối thiểu 4, tối đa 7
  • cao (5): 10, 10, 8, 9, 9, phút 8, tối đa 10

Giá trị trung bình rơi vào thùng giữa, chúng tôi bỏ qua phần còn lại

Chúng tôi tạo ra 3 nhóm: 4, 5-6, 7. Thấp sẽ bắt đầu với số lượng 5 và tối đa là 3 và cao với tối thiểu 8 và số lượng là 5.

Đối với mỗi số, chúng tôi đếm số lần rơi trong nhóm thấp và cao, tối đa và tối thiểu và giữ cho nhóm ở giữa.

  • cũ thấp (5)
  • thấp (5): 4, 4, 4, 4, 4, tối đa 4
  • giữa (3): 5,6,6
  • cao (2): 7, 7, tối thiểu 7
  • cũ cao (5)

Bây giờ chúng ta có thể tính toán trung vị trực tiếp: chúng ta có một tình huống như thế này

old low    low          middle  high  old high
x x x x x  4 4 4 4 4 4   5 6 6  7 7   x x x x x

vì vậy trung vị là 4,5.

Giả sử bạn biết một chút về phân phối, bạn có thể tinh chỉnh cách xác định phạm vi để tối ưu hóa tốc độ. Trong mọi trường hợp, hiệu suất nên đi với O (N), vì 1 + 1/3 + 1/9 ... = 1.5

Bạn cần tối thiểu và tối đa vì các trường hợp cạnh (ví dụ: nếu trung vị là trung bình giữa mức tối đa cũ thấp và phần tử tiếp theo).

Tất cả các hoạt động này có thể được song song, bạn có thể cung cấp 1/100 dữ liệu cho mỗi máy tính và tính toán 3 nhóm trong mỗi nút, sau đó phân phối nhóm bạn giữ. Điều này một lần nữa khiến bạn sử dụng mạng hiệu quả vì mỗi số được truyền trung bình 1,5 lần (vì vậy O (N)). Bạn thậm chí có thể đánh bại rằng nếu bạn chỉ chuyển các số tối thiểu giữa các nút (ví dụ: nếu nút 1 có 100 số và nút 2 có 150 số, thì nút 2 có thể cung cấp 25 số cho nút 1).

Trừ khi bạn biết nhiều hơn về phân phối, tôi nghi ngờ bạn có thể làm tốt hơn O (N) ở đây, bởi vì bạn thực sự cần phải đếm các yếu tố ít nhất một lần.


1
Không phải là trường hợp thực sự tồi tệ hơn (đối với thuật toán của bạn) khi tất cả các số bằng nhau? Nếu tôi đúng, sẽ không có thùng nào của bạn được đổ đầy từ thùng giữa, với tất cả các yếu tố. Do đó, bạn sẽ phải duyệt qua tất cả các yếu tố mỗi lần, tiến triển nhanh theo cấp số nhân đến giữa khoảng. Tôi tin rằng nó sẽ là một O(n log n)trong trường hợp đó. Liệu nó có ý nghĩa? Nhân tiện, tôi thích ý tưởng của bạn
Dici

1
@Dici không thực sự: trước hết bạn có thể dễ dàng rút ngắn kịch bản "tất cả giống nhau" vì bạn biết tối thiểu và tối đa. Như tôi đã nói trong câu trả lời, việc biết phân phối có thể thúc đẩy các lựa chọn xô lệch của bạn; thứ hai, nó vẫn sẽ vẫn o(n)+o(n/3)+o(n/9)+...còn o(n)và không o(n log n).
Sklivvz

Mặt khác, có lẽ có một trường hợp xấu nhất khác, phân phối hình chữ U. Tôi cần suy nghĩ một chút về nó, chính thức hóa trường hợp xấu nhất, nhưng nó có thể có thể làm tồi tệ hơn o(n)trong trường hợp đó, với phân vùng ngây thơ.
Sklivvz

Mmm yeah, min và max sẽ giúp xử lý trường hợp "tất cả giống nhau" khá dễ dàng
Dici

2

Một phương pháp dễ dàng hơn là có số có trọng số.

  • Chia tập hợp lớn giữa các máy tính
  • Sắp xếp từng bộ
  • Lặp lại thông qua tập nhỏ và tính trọng số cho các phần tử lặp lại
  • hợp nhất mỗi bộ 2 thành 1 (mỗi bộ đã được sắp xếp) cập nhật trọng số
  • tiếp tục hợp nhất các bộ cho đến khi bạn chỉ nhận được một bộ
  • Lặp lại thông qua trọng số tích lũy này cho đến khi bạn đạt được OneBillion / 2

1

Chia 10 ^ 9 số, 10 ^ 7 cho mỗi máy tính ~ 80 MB cho mỗi máy tính. Mỗi máy tính sắp xếp số của nó. Sau đó, máy tính 1 hợp nhất sắp xếp các số riêng của nó với các số từ máy tính 2, máy tính 3 và 4, v.v ... Sau đó, máy tính 1 ghi một nửa số đó thành 2, 3 đến 4, v.v. Sau đó, 1 hợp nhất sắp xếp các số từ máy tính 1,2,3,4, viết lại chúng. Và như thế. Tùy thuộc vào kích thước RAM trên các máy tính mà bạn có thể thoát khỏi việc không ghi lại tất cả các số cho từng máy tính, bạn có thể tích lũy các số trên máy tính 1 trong vài bước, nhưng bạn có thể làm toán.

Ồ, cuối cùng cũng nhận được giá trị trung bình của các giá trị 500000000 và 500000001 (nhưng kiểm tra xem có đủ 00 trong đó không, tôi không biết).

EDIT: @Roman - tốt nếu bạn không thể tin nó ngay cả khi đó là sự thật thì không có lý do gì để tôi tiết lộ sự thật hay sự giả dối của đề xuất. Điều tôi muốn nói là lực lượng vũ phu đôi khi đánh bại thông minh trong một cuộc đua. Tôi mất khoảng 15 giây để đưa ra một thuật toán mà tôi tin tưởng rằng tôi có thể thực hiện được, nó sẽ hoạt động và có thể thích ứng với nhiều kích cỡ đầu vào và số lượng máy tính, và có thể điều chỉnh theo các đặc điểm của máy tính và sắp xếp mạng. Nếu bạn hoặc bất kỳ ai khác phải mất 15 phút để nghĩ ra thuật toán phức tạp hơn, tôi có lợi thế 14m45 để mã hóa giải pháp của mình và bắt đầu chạy.

Nhưng tôi thoải mái thừa nhận đây là tất cả sự khẳng định, tôi chưa đo lường được gì.


ở đây chúng tôi chỉ hợp nhất tất cả các số. Chúng ta có thể làm điều đó theo cách tốt hơn bằng cách sử dụng: - "chúng ta có thể tìm thấy trung vị của hai danh sách được sắp xếp trong thời gian đăng nhập. N là độ dài của mỗi danh sách."
anony

1
@anony - trong khi bạn trả lời câu hỏi của riêng mình, tôi sẽ giải quyết, kiểm tra và thực hiện. Tôi hy vọng rằng có những cách tốt hơn, nhưng đôi khi song song một cách đơn giản để tôi tự do gãi đầu về những vấn đề thực sự khó khăn.
Dấu hiệu suất cao

Bạn đã thực sự làm nó trong 7 phút? Tôi không thể tin rằng ngay cả khi đó là sự thật. Tôi đã thực hiện nhiệm vụ tương tự (đó là một bài tập đại học) và mất khoảng 2 giờ để thực hiện và kiểm tra tất cả các công cụ từ xa (tôi đã sử dụng java RMI).
La Mã

Tôi thấy những gì bạn đang nói, nhưng với cùng một mã thông báo, DrPizza có một giải pháp nhanh hơn để suy nghĩ, đó là sắp xếp tất cả dữ liệu trên một nút và bỏ qua 99. Không ai trong chúng ta biết dữ liệu đắt như thế nào chuyển nhượng nên được xem xét, vì vậy tất cả chúng ta chỉ chọn một thỏa hiệp nghe có vẻ hợp lý. Giải pháp của bạn chuyển tất cả dữ liệu nhiều lần, vì vậy tôi hơi nghi ngờ về điều đó, nhưng chắc chắn đó là một giải pháp.
Steve Jessop

'mơ hồ hợp lý' - điều đó đủ tốt cho tôi @Steve! Đặc biệt là để trả lời cho một câu hỏi mơ hồ.
Đánh dấu hiệu suất cao

1

Điều này có thể được thực hiện trên các nút sử dụng dữ liệu không được sắp xếp trên các nút (nói từ các tệp nhật ký) theo cách sau.

Có 1 nút cha và 99 nút con. Các nút con có hai cuộc gọi api:

  • stats (): trả về min, max và đếm
  • so sánh (median_guess): trả về giá trị khớp với số đếm, đếm nhỏ hơn giá trị và đếm lớn hơn giá trị

Nút cha gọi số liệu thống kê () trên tất cả các nút con, lưu ý mức tối thiểu và tối đa của tất cả các nút.

Một tìm kiếm nhị phân bây giờ có thể được tiến hành theo cách sau:

  1. Bỏ qua việc làm tròn tối thiểu và tối đa - đây là 'dự đoán' trung bình
  2. Nếu số lớn hơn số đếm lớn hơn số đếm nhỏ hơn, hãy đặt mức tối thiểu thành đoán
  3. Nếu số lớn hơn số đếm nhỏ hơn số đếm nhỏ hơn, hãy đặt mức tối đa thành đoán
  4. Nếu số là kết thúc lẻ khi tối thiểu và tối đa bằng nhau
  5. Nếu số lượng thậm chí kết thúc khi tối đa <= tối thiểu + đoán.match_count Điều này có thể được thực hiện trên các nút sử dụng dữ liệu chưa được sắp xếp (nói từ tệp nhật ký) theo cách sau.

Có 1 nút cha và 99 nút con. Các nút con có hai cuộc gọi api:

  • stats (): trả về min, max và đếm
  • so sánh (median_guess): trả về giá trị khớp với số đếm, đếm nhỏ hơn giá trị và đếm lớn hơn giá trị

Nút cha gọi số liệu thống kê () trên tất cả các nút con, lưu ý mức tối thiểu và tối đa của tất cả các nút.

Một tìm kiếm nhị phân bây giờ có thể được tiến hành theo cách sau:

  1. Bỏ qua việc làm tròn tối thiểu và tối đa - đây là 'dự đoán' trung bình
  2. Nếu số lớn hơn số đếm lớn hơn số đếm nhỏ hơn, hãy đặt mức tối thiểu thành đoán
  3. Nếu số lớn hơn số đếm nhỏ hơn số đếm nhỏ hơn, hãy đặt mức tối đa thành đoán
  4. Nếu số là kết thúc lẻ khi tối thiểu và tối đa bằng nhau
  5. Nếu số lượng thậm chí kết thúc khi tối đa <= tối thiểu + đoán.match_count

Nếu các số liệu thống kê () và so sánh () có thể được tính toán trước với sắp xếp O (N / Mlogn / M), thì phép tính trước O (N / M) với độ phức tạp bộ nhớ là O (N) cho trước phép tính. Sau đó, bạn có thể so sánh () trong thời gian không đổi, vì vậy toàn bộ (bao gồm cả tính toán trước) sẽ chạy trong O (N / MlogN / M) + O (logN)

Hãy cho tôi biết nếu tôi đã phạm sai lầm!


vâng tôi chỉ cần tìm kiếm nhị phân. Sẽ tiết kiệm băng thông mạng chỉ gọi mỗi máy tính một vài lần. Ngoài ra, mỗi máy có thể có một "trục" trong đó nó thay đổi số ở hai bên của trục để tiết kiệm thời gian. (trục sẽ là ước tính trung bình trước đó, vì vậy lần sau, chỉ phải đi qua tất cả các số ở một bên của trục)
vua robert

0

Làm thế nào về điều này: - mỗi nút có thể mất 1Billion / 100 số. Tại mỗi nút, các phần tử có thể được sắp xếp và có thể tìm thấy trung vị. Tìm trung vị của trung vị. chúng ta có thể, bằng cách tổng hợp số lượng các số nhỏ hơn trung vị trên tất cả các nút tìm ra x%: y% chia mà trung bình tạo ra. Bây giờ yêu cầu tất cả các nút xóa các phần tử nhỏ hơn trung vị trung vị (lấy ví dụ về tỷ lệ chia 30%: 70%) .30% số bị xóa. 70% của 1Billion là 700 triệu. Bây giờ tất cả các nút đã xóa ít hơn 3 triệu nút có thể gửi các nút bổ sung đó trở lại máy tính chính. Máy tính chính phân phối lại theo cách mà bây giờ tất cả các nút sẽ có số lượng nút gần như bằng nhau (7 triệu). Bây giờ vấn đề đã giảm xuống còn 700 triệu số .... tiếp tục cho đến khi chúng ta có một tập nhỏ hơn có thể được tính trên một comp.


Về bản chất, chúng tôi luôn giảm ít nhất 30% vấn đề và chúng tôi đang đạt được rất nhiều tính toán song song thông qua việc này. Mỗi nút bắt đầu với 10 triệu và giảm 30% dữ liệu được đặt trong mỗi lần lặp.
anony

Trong lần lặp đầu tiên, chúng tôi tìm kiếm số 500Millionth. Trong lần lặp thứ hai - nếu số lượng số bị xóa là 300 triệu thì chúng ta tìm số thứ 200 và cứ thế ...
anony

2
Điều này có vẻ như đang đi đúng hướng, nhưng bạn không giải thích rõ ràng làm thế nào để tránh vứt bỏ trung vị một cách tình cờ với tỷ lệ chia 30% / 70% của bạn. Lấy ví dụ sau: giả sử 29% đầu tiên của bạn là tất cả các số 0 và tất cả các khối khác được tính bằng 1000, và mỗi bộ khối nhiều hơn một khối. Trung bình phần trăm thứ 30 sẽ loại bỏ tất cả 29% dữ liệu và chỉ dưới một nửa 61% dữ liệu, tức là 29 + 30% = 59% dữ liệu. Rất tiếc, chúng tôi đã ném ra trung vị thực sự! Vì vậy, rõ ràng bạn không có nghĩa là, hoặc ít nhất bạn có nghĩa là nó thông minh hơn tôi giải thích.
Rex Kerr

0

Trước tiên chúng ta hãy tìm cách tìm một trung bình gồm n số trên một máy duy nhất: về cơ bản tôi đang sử dụng chiến lược phân vùng.

Bài toán: lựa chọn (n, n / 2): Tìm số thứ n / 2 từ số nhỏ nhất.

Bạn chọn nói phần tử trung bình k và dữ liệu phân vùng thành 2 mảng phụ. phần 1 chứa tất cả các phần tử <k và thứ 2 chứa tất cả các phần tử> = k.

if sizeof (mảng con thứ 1)> = n / 2, bạn biết rằng mảng con này chứa trung vị. Sau đó, bạn có thể loại bỏ mảng con thứ 2. Giải quyết lựa chọn vấn đề này (sizeof mảng con thứ 1, n / 2) .

Trong trường hợp khác, loại bỏ phân đoạn thứ 1 này và giải quyết lựa chọn (phân đoạn thứ hai, n / 2 - sizeof (phân đoạn thứ nhất))

Làm điều đó đệ quy.

độ phức tạp thời gian là O (n) thời gian dự kiến.

Bây giờ nếu chúng ta có nhiều máy, trong mỗi lần lặp, chúng ta phải xử lý một mảng để phân tách, chúng ta phân phối mảng thành các máy khác. Mỗi máy xử lý khối mảng của chúng và gửi lại bản tóm tắt cho máy điều khiển trung tâm tức là kích thước của phân đoạn thứ nhất và kích thước của phân đoạn thứ hai. Các máy trung tâm cộng các bản tóm tắt và quyết định phân đoạn nào (thứ 1 hoặc thứ 2) để xử lý thêm và tham số thứ 2 của lựa chọn và gửi lại cho mỗi máy. và như thế.

Thuật toán này có thể được thực hiện rất gọn gàng bằng cách sử dụng bản đồ giảm?

Trông nó như thế nào?


0

Tôi nghĩ câu trả lời của Steve Jessop sẽ là nhanh nhất.

Nếu kích thước truyền dữ liệu mạng là nút cổ chai, thì đây là một cách tiếp cận khác.

Divide the numbers into 100 computers (10 MB each). 
Loop until we have one element in each list     
    Find the meadian in each of them with quickselect which is O(N) and we are processing in parallel. The lists will be partitioned at the end wrt median.
    Send the medians to a central computer and find the median of medians. Then send the median back to each computer. 
    For each computer, if the overall median that we just computed is smaller than its median, continue in the lower part of the list (it is already partitioned), and if larger in the upper part.
When we have one number in each list, send them to the central computer and find and return the median.

32 MB mỗi cái, ý bạn là gì?
Dici

Bạn có ý nghĩa gì khi tiếp tục ở phần dưới của danh sách?
Ruthvik Vaila

0

Tôi sẽ làm như thế này:

trong đầu tất cả 100 công việc để tìm số cao nhất và thấp nhất; mỗi máy tính có một phần cơ sở dữ liệu / tệp mà nó truy vấn;

khi tìm thấy số cao nhất và thấp nhất, một máy tính sẽ đọc dữ liệu và phân phối từng số một cách đồng đều cho phần còn lại của 99; các số được phân phối theo các khoảng bằng nhau; (người ta có thể mất từ ​​-100 triệu đến 0, người khác - từ 0 đến 100 triệu, v.v.);

Trong khi nhận số, mỗi trong số 99 máy tính đã sắp xếp chúng;

Sau đó, thật dễ dàng để tìm trung vị ... Xem mỗi máy tính có bao nhiêu số, thêm tất cả chúng (tổng của có bao nhiêu số, không phải chính các số đó), chia cho 2; tính toán trong đó máy tính là số, và tại chỉ số nào;

:) voilla

PS Có vẻ có rất nhiều nhầm lẫn ở đây; MEDIAN - là SỐ TRONG TRUNG TÂM DANH SÁCH SỐ LƯỢNG CÓ HẠN!


0

Bạn có thể sử dụng phương pháp cây giải đấu để tìm trung vị. Chúng ta có thể tạo một cây với 1000 nút rời sao cho mỗi nút lá là một mảng. Sau đó, chúng tôi tiến hành n / 2 giải đấu giữa các mảng khác nhau. Giá trị ở gốc sau khi giải đấu n / 2 là kết quả.

http://www.geekforgeek.org/touriga-tree-and-binary-heap/


0

Nếu các số không khác biệt và chỉ thuộc về một phạm vi nhất định, nghĩa là chúng được lặp lại, thì một giải pháp đơn giản xuất hiện trong đầu tôi là phân phối các số trong 99 máy bằng nhau và giữ một máy làm chủ. Bây giờ mọi máy đều lặp lại các số đã cho và lưu số đếm của từng số trong một bộ băm. Mỗi lần số được lặp lại trong tập hợp số được phân bổ cho máy tính cụ thể đó, nó sẽ cập nhật số của nó trong tập băm.

Tất cả các máy sau đó trả lại bộ băm của chúng cho máy chủ. Máy chủ kết hợp các bộ băm, tổng hợp số lượng của cùng một khóa được tìm thấy trong một bộ băm. Ví dụ, bộ băm của máy số 1 có một mục nhập ("1", 7) và bộ băm của máy số 2 có một mục nhập ("1", 9), do đó, máy chủ khi kết hợp các bộ băm tạo ra một mục nhập của ("1", 16), v.v.

Khi các bộ băm đã được hợp nhất, sau đó chỉ cần sắp xếp các khóa và bây giờ bạn có thể dễ dàng tìm thấy mục (n / 2) và mục (n + 2/2), từ bộ băm được sắp xếp.

Phương pháp này sẽ không có lợi nếu số tỷ là khác biệt.


0

Chà, giả sử bạn biết rằng số lượng số nguyên khác nhau là (4 tỷ), sau đó bạn có thể xô chúng vào các thùng 64k và nhận được số lượng phân phối cho mỗi nhóm từ mỗi máy trong cụm (100 máy tính). Kết hợp tất cả các tính này. Bây giờ, hãy tìm cái xô có trung vị và lần này chỉ yêu cầu các thùng cho các phần tử 64k sẽ nằm trong thùng mục tiêu của bạn. Điều này yêu cầu O (1) (cụ thể là 2) truy vấn trên "cụm" của bạn. : D


0

Giá trị đồng xu của tôi, sau tất cả những gì đã được đưa lên bởi những người khác:

Tìm trung vị trên một máy duy nhất là O (N): https://en.wikipedia.org/wiki/Selection_alacticm .

Gửi số N đến 100 máy cũng là O (N). Vì vậy, để làm cho việc sử dụng 100 máy trở nên thú vị, giao tiếp phải tương đối nhanh hoặc N lớn đến mức một máy không thể xử lý được trong khi N / 100 có thể thực hiện được hoặc chúng tôi chỉ muốn xem xét vấn đề toán học mà không bận tâm về dữ liệu cộng đồng.

Do đó, để cắt ngắn mọi thứ tôi sẽ cho rằng, trong giới hạn hợp lý, chúng tôi có thể gửi / phân phối số mà không ảnh hưởng đến phân tích hiệu quả.

Hãy xem xét cách tiếp cận sau đây, trong đó một máy được chỉ định là "chính" cho một số xử lý chung. Điều này sẽ tương đối nhanh, do đó, "bậc thầy" cũng tham gia vào các tác vụ chung mà mỗi máy thực hiện.

  1. Mỗi máy nhận được N / 100 số, tính toán trung vị của chính nó và gửi thông tin đó cho chủ.
  2. Bậc thầy tổng hợp một danh sách được sắp xếp của tất cả các trung vị riêng biệt và gửi lại cho mỗi máy, xác định một chuỗi các xô theo thứ tự (trên mỗi máy giống nhau), một cho mỗi giá trị trung bình (một thùng giá trị đơn) và một cho mỗi khoảng giữa dải phân cách liền kề. Tất nhiên, cũng có các nhóm cấp thấp hơn và cấp cao hơn cho các giá trị dưới mức trung bình thấp nhất và trên mức cao nhất.
  3. Mỗi máy tính có bao nhiêu số rơi vào mỗi nhóm và truyền thông tin đó trở lại cho chủ.
  4. Bậc thầy xác định thùng nào chứa trung vị, có bao nhiêu giá trị thấp hơn (tổng cộng) giảm xuống dưới thùng đó và bao nhiêu giá trị ở trên.
  5. Nếu nhóm được chọn là nhóm giá trị đơn (một trong các giá trị trung bình), hoặc nhóm đã chọn chỉ chứa 1 (N lẻ) hoặc 2 (N chẵn) chúng ta đã hoàn thành. Mặt khác, chúng tôi lặp lại các bước trên với các sửa đổi (rõ ràng) sau:
  6. Chỉ các số từ nhóm được chọn mới được (phân phối lại) từ máy chính đến 100 máy và hơn thế nữa
  7. Chúng tôi sẽ không tính toán (trên mỗi máy) trung vị, nhưng giá trị thứ k, trong đó chúng tôi tính đến có bao nhiêu số cao hơn đã bị loại bỏ khỏi tổng số và bao nhiêu số thấp hơn. Về mặt khái niệm, mỗi máy cũng có phần của các số thấp / cao bị loại bỏ và tính đến điều đó khi tính toán trung vị mới trong tập hợp (về mặt khái niệm) bao gồm (phần của nó) các số bị loại bỏ.

Độ phức tạp thời gian:

  1. Một chút suy nghĩ sẽ thuyết phục bạn rằng ở mỗi bước, tổng số giá trị cần phân tích giảm đi ít nhất hai nhân tố (2 sẽ là một trường hợp khá bệnh; bạn có thể mong đợi giảm tốt hơn đáng kể). Từ đây, chúng tôi nhận được:
  2. Giả sử rằng việc tìm giá trị trung bình (hoặc giá trị k-th), là O (N), sẽ mất thời gian c * N trong đó tiền tố c không thay đổi quá lớn với N để chúng ta có thể lấy nó làm hằng số trong thời điểm này, chúng ta sẽ nhận được kết quả cuối cùng của chúng tôi trong tối đa 2 * c * N / 100 lần. Do đó, sử dụng 100 máy mang lại cho chúng tôi hệ số tăng tốc 100/2 (ít nhất là).
  3. Như đã nhận xét ban đầu: thời gian liên quan đến việc giao tiếp các con số giữa các máy có thể khiến nó trở nên hấp dẫn hơn khi chỉ cần làm mọi thứ trên một máy. Tuy nhiên, NẾU chúng ta sử dụng phương pháp phân tán, tổng số lượng số được truyền đạt trong tất cả các bước cùng nhau sẽ không vượt quá 2 * N (N lần đầu tiên, <= N / 2 lần thứ hai, <= một nửa số đó thứ ba, v.v.)

-1
  1. Chia 1 tỷ số thành 100 máy. Mỗi máy sẽ có 10 ^ 7 số.

  2. Đối với mỗi số đến máy, lưu số trong bản đồ tần số, số -> đếm. Cũng lưu trữ số lượng tối thiểu trong mỗi máy.

  3. Tìm trung vị trong mỗi máy: bắt đầu từ số min trong mỗi máy, tính tổng cho đến khi đạt được chỉ số trung vị. Trung vị trong mỗi máy, sẽ là khoảng. nhỏ hơn và lớn hơn 5 * 10 ^ 6 số.

  4. Tìm trung vị của tất cả các trung vị, sẽ nhỏ hơn và lớn hơn khoảng. 50 * 10 ^ 7 số, là trung vị của 1 tỷ số.

Bây giờ một số tối ưu hóa của bước thứ 2: Thay vì lưu trữ trong bản đồ tần số, hãy lưu trữ số đếm trong một mảng bit thay đổi. Ví dụ: Hãy nói bắt đầu từ số min trong một máy, đây là các tần số:

[min number] - 8 count
[min+1 number] - 7 count
[min+2 number] - 5 count

Ở trên có thể được lưu trữ trong mảng bit như:

[min number] - 10000000
[min+1 number] - 1000000
[min+2 number] - 10000

Lưu ý rằng hoàn toàn sẽ có giá khoảng 10 ^ 7 bit cho mỗi máy, vì mỗi máy chỉ xử lý 10 ^ 7 số. 10 ^ 7 bit = 1,25 * 10 ^ 6 byte, là 1,25 MB

Vì vậy, với cách tiếp cận trên, mỗi máy sẽ cần 1,25 MB dung lượng để tính toán trung vị cục bộ. Và trung vị của trung vị có thể được tính từ 100 trung vị địa phương đó, dẫn đến trung bình là 1 tỷ số.


Nếu số lượng là số float thì sao?
Sklivvz

-1

Tôi đề nghị một phương pháp để tính toán trung bình. :) Nếu một tỷ số này theo thứ tự ngẫu nhiên, tôi nghĩ rằng tôi có thể chọn ngẫu nhiên 1/100 hoặc 1/10 của một tỷ số, sắp xếp chúng với 100 máy, sau đó chọn trung vị của chúng. Hoặc hãy chia hàng tỷ số thành 100 phần, hãy để mỗi máy chọn 1/10 mỗi phần một cách ngẫu nhiên, tính trung bình của chúng. Sau đó, chúng ta có 100 số và chúng ta có thể tính trung bình của số 100 dễ dàng hơn. Chỉ là một gợi ý, tôi không chắc nó có đúng về mặt toán học không. Nhưng tôi nghĩ bạn có thể hiển thị kết quả cho một người quản lý không giỏi về toán học.


Rõ ràng là không đúng và tôi thực sự khuyên bạn đừng bao giờ cho rằng người phỏng vấn của bạn là một con lợn ngu ngốc mà bạn có thể lừa
Dici

Haha ok, mặc dù nó không thay đổi thực tế câu trả lời của bạn là không chính xác. Thật dễ dàng để chứng minh điều đó
Dici

OK, sau khi đọc một số bài giảng về thống kê, tôi nghĩ rằng ý tưởng chọn 1/100 hoặc thậm chí 1/1000 ngẫu nhiên một tỷ số và tính trung bình của chúng không phải là quá tệ. Nó chỉ là một tính toán gần đúng.
Lazyboy

-3

Câu trả lời của Steve Jessop là sai:

xem xét bốn nhóm sau:

{2, 4, 6, 8, 10}

{21, 21, 24, 26, 28}

{12, 14, 30, 32, 34}

{16, 18, 36, 38, 40}

Trung vị là 21, được chứa trong nhóm thứ hai.

Trung vị của bốn nhóm là 6, 24, 30, 36, Tổng trung vị là 27.

Vì vậy, sau vòng lặp đầu tiên, bốn nhóm sẽ trở thành:

{6, 8, 10}

{24, 26, 28}

{12, 14, 30}

{16, 18, 36}

21 đã bị loại bỏ sai.

Thuật toán này chỉ hỗ trợ trường hợp khi có hai nhóm.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.