Làm thế nào để đếm trong trường hợp xấu nhất thời gian tuyến tính?


8

Câu hỏi nàycâu hỏi này khiến tôi suy nghĩ một chút. Để sắp xếp một mảng có độ dài với phần tử duy nhất trong , chúng ta cần có khả năng lưu trữ số lượng giá trị trong mảng. Có một số gợi ý, nhưng tôi đang tìm cách để làm điều này trong trường hợp tuyến tính tồi tệ nhất. Cụ thể hơn:nkO(n+klogk)

Cho một danh sách số nguyên tố với yếu tố riêng biệt, xác định một danh sách các hàng của tất cả các yếu tố độc đáo mà c_i là đếm của nguyên tố x_i trong Một .AnkU={(xi,ci)}kxiAcixiA

Dưới đây là một số ý tưởng (thất bại) tôi đã có và đã được đề xuất:

  1. Cây tìm kiếm nhị phân cân bằng - Với điều này, sẽ mất O(logk) để chèn vào cây và tăng giá trị. Sau khi chèn chúng ta có thể thực hiện một giao dịch cây trong O(k) . Do đó, tổng thời gian đi ra O(nlogk) quá chậm.
  2. Bản đồ băm - Với điều này, chúng ta có thể nhận được O(1) chèn dự kiến và do đó O(n) thời gian dự kiến . Tuy nhiên, đây vẫn không phải là trường hợp xấu nhất O(n) .
  3. Trống Space Mapping - Tìm thiểu và yếu tố tối đa trong A . Phân bổ (nhưng không khởi tạo) đủ bộ nhớ để bao phủ phạm vi này. Sử dụng bộ nhớ này về cơ bản như một bản đồ băm và bao gồm một hàm băm ngẫu nhiên để chúng ta không cố gắng truy cập bộ nhớ bị hỏng. Chiến lược này trình bày các vấn đề. (1) Đó là xác suất với xác suất thất bại rất rất thấp, nhưng vẫn không được bảo đảm. Sử dụng bộ nhớ như thế này giới hạn chúng ta với các ràng buộc số nguyên hoặc dấu phẩy động.
  4. Mảng liên kết - Có nhiều mảng kết hợp khác có thể được sử dụng, tương tự như bản đồ băm và BST, nhưng tôi không tìm thấy bất kỳ mảng nào khớp với các ràng buộc này.

Có thể có một số phương pháp rõ ràng tôi đang thiếu, nhưng tôi cũng nghĩ rằng nó có thể không có khả năng. Quan điểm của bạn là gì?


3
Không thể thực hiện được trong mô hình so sánh vì vấn đề phân biệt thành phần có giới hạn thấp hơn về độ phức tạp của cây quyết định . Ω(nlogn)
John L.

@ Apass.Jack, ồ đúng rồi. Một sự giảm bớt tầm thường tôi đã không xem xét. Nếu bạn viết nó lên như một câu trả lời nhanh chóng, tôi sẽ chấp nhận.
ryan

Tại sao HashMap không được đảm bảo khấu hao O (n) ?
javadba

1
@javadba Ví dụ: giả sử tất cả các yếu tố được băm đến cùng một giá trị.
John L.

Ah ok vậy nếu nó là một băm không hoàn hảo.
javadba

Câu trả lời:


6

Đây là một câu hỏi hay.

Trong mô hình so sánh hay, nói chung hơn, mô hình cây quyết định đại số, vấn đề phân biệt thành phần có giới hạn thấp hơn về độ phức tạp thời gian của trong trường hợp xấu nhất như đã nói trong bài viết Wikipedia này . Vì vậy, không có thuật toán để đếm các yếu tố khác biệt trong thời gian tuyến tính trong trường hợp xấu nhất, thậm chí không tính các điểm trùng lặp.Θ(nlogn)

Tuy nhiên, không rõ liệu nó có thể được thực hiện trong một mô hình tính toán khác hay không. Dường như không có khả năng trong bất kỳ mô hình tính toán xác định hợp lý nào.


Đây thực sự là một ví dụ của vấn đề phân biệt yếu tố? Chỉ cần tạo các bộ dữ liệu không yêu cầu kiểm tra tính khác biệt. Không đồng ý, chỉ tò mò.
mascoj

2
Điều tôi đang nói là, nếu bạn có thể tạo ra bộ phần tử riêng biệt đó, thì bạn cũng có thể giải quyết vấn đề về tính khác biệt của phần tử bằng cách kiểm tra xem kích thước của bộ dữ liệu có phải là . n
John L.

Cuộc gọi tốt Cảm ơn
mascoj

1

Có tồn tại các thuật toán ngẫu nhiên có thời gian chạy dự kiến ​​là O(n) ; hoặc trong đó xác suất thời gian chạy lâu hơn cn là nhỏ theo cấp số nhân trong c .

Cụ thể, chọn ngẫu nhiên một hàm băm 2 phổ, sau đó sử dụng nó để băm tất cả các phần tử của mảng. Điều này đạt được thời gian chạy đã nêu, nếu bạn chọn độ dài của đầu ra của hàm băm 2 phổ một cách thích hợp.

Một ví dụ khác, bạn có thể xây dựng một thuật toán ngẫu nhiên mà trường hợp xấu nhất thời gian chạy là O(n) (nó luôn luôn chạy trong thời gian tuyến tính, không có vấn đề gì) và có một xác suất lỗi của ít nhất 1/2100 . (Làm thế nào? Chạy thuật toán trên và chấm dứt nó nếu nó chạy lâu hơn cn bước đối với một số lựa chọn phù hợp c .) Trong thực tế, điều đó đủ tốt, vì xác suất máy tính của bạn đưa ra câu trả lời sai do tia vũ trụ đã có nhiều hơn 1/2100 .


1

Cách tiếp cận 3 của bạn có thể được thực hiện an toàn bằng cách sử dụng giải pháp để thực hiện 2.12 của Aho, Hopcroft và Ullman (1974) Thiết kế và phân tích thuật toán máy tính như được mô tả, ví dụ, trong Sử dụng bộ nhớ chưa được khởi tạo để giải trí và kiếm lợi nhuận .

Về cơ bản, ngoài mảng các phần tử N của bạn với số đếm, bạn có hai mảng gồm các phần tử N và một số phụ trợ để tạo ra một tập hợp thưa cho biết số đếm nào là hợp lệ.

Trong mã giả giống như C:

uint* a = malloc(n);
uint* b = malloc(n);
uint* c = malloc(n);
uint len = 0;

get_count(uint x) {
    uint idx = a[x];
    return idx >= 0 && idx < len && b[idx] == x ? c[idx] : 0;
}

increment_count(uint x) {
    uint idx = a[x];
    if (idx < 0 || idx >= len || b[idx] != x) {
        idx = len;
        len++;
        a[x] = idx;
        b[idx] = x;
        c[idx] = 0;
    }
    c[idx]++;
}

Triển khai thực tế của tập thưa thớt được thảo luận trong câu trả lời StackOverflow này .


PS ccó thể được lập chỉ mục trên xhoặc idx, nhưng tôi đã sử dụng idxcho địa phương bộ đệm tốt hơn.
Peter Taylor

Tôi thích câu trả lời, nhưng tôi đã nhầm lẫn về những gì làm cho điều này an toàn. Trong khi, hoàn toàn không thể, bạn không thể truy cập vào một ô nhớ, bởi một phép lạ nào đó có mục "hợp lệ" trong đó mặc dù nó không bao giờ được đặt ở đó. Nếu bạn không may mắn với malloc?
ryan

1
1..uuO(1)

@ryan, xem nghiên cứu.swtch.com / sparsh để biết những gì làm cho nó an toàn. Đó chắc chắn là một mẹo rất thông minh.
DW

3u+1u{a,b,c,len}cu=5123=134217728(3×512+1)(1+2k)k
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.