Bộ máy tính chênh lệch giữa hai bộ lớn


14

Tôi có hai bộ lớn của các số nguyên và . Mỗi bộ có khoảng một triệu mục nhập và mỗi mục là một số nguyên dương dài tối đa 10 chữ số. AB

Thuật toán tốt nhất để tính và gì? Nói cách khác, làm thế nào tôi có thể tính toán hiệu quả danh sách các mục của không có trong và ngược lại? Điều gì sẽ là cấu trúc dữ liệu tốt nhất để đại diện cho hai bộ này, để làm cho các hoạt động này hiệu quả?B Một Một BABBAAB

Cách tiếp cận tốt nhất tôi có thể đưa ra là lưu trữ hai bộ này dưới dạng danh sách được sắp xếp và so sánh mọi yếu tố của A với mọi yếu tố của B , theo kiểu tuyến tính. Chúng ta có thể làm tốt hơn không?


Nếu bạn sẵn sàng lưu trữ nó khác nhau, bạn có thể có được kết quả tốt hơn.
Realz Slaw

Ngoài ra, nếu bạn sẵn sàng nhận kết quả dưới dạng cấu trúc dữ liệu ngầm; bạn chỉ có thể tạo một cấu trúc như vậy để truy vấn hai bộ để trả lời từng truy vấn của riêng nó.
Realz Slaw

1
@ user917279 Một điểm lớn là: bạn thường có thể đánh đổi thời gian tiền xử lý / xây dựng, thời gian truy vấn và sử dụng bộ nhớ với nhau. Bạn có chỉnh sửa structe hiếm khi, nhưng truy vấn rất nhiều? Cách khác vòng? Bộ nhớ có phải là mối quan tâm hay không? Những câu hỏi như vậy có thể được trả lời từ quan điểm thực tế và cho biết sự lựa chọn của cấu trúc "đúng" "lý thuyết".
Raphael

1
@Raphael Bạn có đề nghị một người có thể làm tốt hơn các bộ liên tục liên tục (về độ phức tạp) bằng cách sử dụng nhiều bộ nhớ hơn và / hoặc dành nhiều thời gian hơn cho việc chuẩn bị. Tôi chỉ tò mò nếu bạn nghĩ rằng nó có thể. Tôi không thấy các bảng tra cứu là một tùy chọn cho các bộ đầu vào có kích thước này.
smossen

1
@ user917279 Nếu bạn xem xét ví dụ về hai tập hợp lớn giống hệt nhau, thì bất kỳ cấu trúc dữ liệu nào được tạo bằng cách sử dụng hàm băm sẽ hỗ trợ kiểm tra tính bằng trong O (1) vì các cấu trúc bằng nhau sẽ được hợp nhất khi được tạo và do đó chia sẻ cùng một vị trí bộ nhớ. Các tập hợp liên tục cũng tận dụng lợi thế của hàm băm khi hai cấu trúc gần như bằng nhau. Sự phức tạp là tốt nhất tôi đã thấy cho đến nay cho các bộ được đặt hàng.
smossen

Câu trả lời:


9

Nếu bạn sẵn sàng lưu trữ các tập hợp trong một cấu trúc dữ liệu chuyên biệt, thì bạn có thể có được một số phức tạp thú vị.

Đặt I=O(min(|A|,|B|,|AΔB|))

Sau đó, bạn có thể thực hiện hoạt động thiết lập A Δ B , mỗi trong O ( Tôi đăng nhập | Một | + | B |AB,AB,ABAΔBthời gian dự kiến. Vì vậy, về cơ bản, bạn có được kích thước tối thiểu của hai bộ, hoặc, kích thước của sự khác biệt đối xứng, tùy theo giá trị nào nhỏ hơn. Điều này là tốt hơn so với tuyến tính, nếu sự khác biệt đối xứng là nhỏ; I E. nếu họ có một ngã tư lớn. Trong thực tế, đối với hai thao tác chênh lệch tập hợp mà bạn muốn, đây thực tế là độ nhạy đầu ra, vì chúng cùng nhau tạo nên kích thước của sự khác biệt đối xứng.O(Ilog|A|+|B|I)

Xem Tập hợp và Bản đồ liên tục của Olle Liljenzin (2013) để biết thêm thông tin.


Các treap trong bài báo được đặt hàng cây tìm kiếm. Tôi sẽ không tính chúng là cấu trúc dữ liệu không được sắp xếp.
smossen

@smossen đủ đúng, tôi chỉnh sửa nó ra.
Realz Slaw

6

Quét tuyến tính là cách tốt nhất mà tôi biết cách thực hiện, nếu các bộ được biểu diễn dưới dạng danh sách liên kết được sắp xếp. Thời gian chạy là .O(|A|+|B|)

Lưu ý rằng bạn không cần so sánh mọi yếu tố của với mọi yếu tố của B , theo cặp. Điều đó sẽ dẫn đến thời gian chạy của O ( | A | × | B | ) , tệ hơn nhiều. Thay vào đó, để tính toán sự khác biệt đối xứng của hai bộ này, bạn có thể sử dụng một kỹ thuật tương tự như thao tác "hợp nhất" trong sáp nhập, được sửa đổi phù hợp để bỏ qua các giá trị chung cho cả hai bộ.ABO(|A|×|B|)

Chi tiết hơn, bạn có thể xây dựng một thuật toán đệ quy như sau để tính , giả sử AB được biểu diễn dưới dạng danh sách được liên kết với các giá trị của chúng theo thứ tự sắp xếp:ABAB

difference(A, B):
    if len(B)=0:
        return A # return the leftover list
    if len(A)=0:
        return B # return the leftover list
    if A[0] < B[0]:
        return [A[0]] + difference(A[1:], B)
    elsif A[0] = B[0]:
        return difference(A[1:], B[1:])  # omit the common element
    else:
        return [B[0]] + difference(A, B[1:])

Tôi đã trình bày điều này bằng giả Python. Nếu bạn không đọc Python, A[0]là người đứng đầu danh sách được liên kết A, A[1:]là phần còn lại của danh sách và +đại diện cho việc ghép các danh sách. Vì lý do hiệu quả, nếu bạn đang làm việc với Python, có lẽ bạn sẽ không muốn triển khai chính xác như trên - ví dụ, có thể tốt hơn khi sử dụng trình tạo, để tránh xây dựng nhiều danh sách tạm thời - nhưng tôi muốn cho bạn thấy những ý tưởng ở dạng đơn giản nhất có thể. Mục đích của mã giả này chỉ là để minh họa thuật toán, không đề xuất một triển khai cụ thể.

ABAB


thật tuyệt vời, chúng ta có các tùy chọn khác nếu các ràng buộc mà các bộ sẽ được lưu trữ khi danh sách được sắp xếp bị loại bỏ không?
dùng917279

2

Nếu A và B có kích thước bằng nhau, tách rời và xen kẽ (ví dụ số lẻ trong A và số chẵn trong B), thì so sánh cặp vật phẩm trong thời gian tuyến tính có thể là tối ưu.

Nếu A và B chứa các khối vật phẩm nằm trong chính xác một trong A hoặc B hoặc trong cả hai vật phẩm đó, thì có thể tính toán độ lệch, liên kết và giao nhau trong thời gian tuyến tính phụ. Ví dụ, nếu A và B khác nhau ở một mục chính xác, thì sự khác biệt có thể được tính trong O (log n).

http://arxiv.org/abs/1301.3388


1
Ông nói rằng các bộ được đặt hàng, có thể có nghĩa là chúng được lưu trữ dưới dạng danh sách, tìm kiếm cây hoặc một cái gì đó khác. Nếu dữ liệu phải được lưu trữ dưới dạng danh sách, sẽ khá không thú vị khi yêu cầu "thuật toán tốt nhất để tính toán AB" khi không có thuật toán nào có thể làm tốt hơn việc quét danh sách theo thời gian tuyến tính (mà anh ta đã tìm thấy thuật toán).
smossen

1
trời ạ, bạn đã liên kết cùng một tờ giấy với tôi (tôi, giống như bạn, đúng hơn) ... đặt tên cho các liên kết của bạn vào lần tới: D
Realz Slaw 14/11/13

@smossen tuyệt vời, với bất kỳ kiến ​​thức nào (?) mà tôi có, tôi đã trình bày chúng dưới dạng danh sách được sắp xếp, nhưng cũng sẽ khiêm tốn chào đón các đề xuất khác.
dùng917279

2

nABab¯một,blà các bitvector. hiệu quả tương đối của kỹ thuật này so với các kỹ thuật khác cũng phụ thuộc vào độ thưa thớt. đối với các tập hợp dày đặc hơn, nó có thể hiệu quả hơn các phương pháp khác. tất nhiên toàn bộ hoạt động là song song lúng túng để các hoạt động thiết lập có thể được thực hiện song song.


Với 1010các mục có thể, vectơ bit hoàn toàn không thực tế.
Raphael

1
R., bỏ lỡ điểm. một đơn longcó thể lưu trữ 32 phần tử hoặc 1 byte, 8 phần tử. vì vậy các mục 1M có thể được lưu trữ chỉ trong ~ 125K RAM! việc lưu trữ có thể hiệu quả hơn đáng kể so với các cách trình bày khác tùy thuộc vào cách thực hiện vấn đề ...
vzn

Vì vậy, bạn cần hơn 12 MB cho các bộ mà OP quan tâm. Điều đó thổi bay tất cả các bộ nhớ cache (hiện tại) và sẽ rất kinh khủng cho các bộ thưa thớt. Cụ thể, việc tạo một tập hợp trống chi phối tất cả các hoạt động khác (đối với các tập thưa thớt). Nhân tiện, Knuth giải quyết vấn đề này trong TAoCP.
Raphael

12 MB? Huh? poster cho biết anh chỉ có 2 bộ. người đăng không chỉ rõ độ thưa / mật độ của bộ ảnh của mình. Điều này được chỉ ra trong câu trả lời của tôi. bạn có cho rằng anh ta có bộ thưa thớt? không có câu trả lời đúng, cách tiếp cận được chỉ ra là một lựa chọn thay thế có thể hữu ích tùy theo hoàn cảnh. nó không được sử dụng phổ biến trong bối cảnh này ...
vzn

Tôi đề nghị bạn đọc lại câu hỏi: "Mỗi bộ có khoảng một triệu mục nhập và mỗi mục nhập là một số nguyên dương dài tối đa 10 chữ số." Có1010 những con số khác nhau có thể xảy ra, và có khoảng 106những người trong danh sách. Điều đó có nghĩa là chỉ 0,01% tất cả các mục trong vectơ bit của bạn là 1 - Tôi thực sự gọi đó là rất thưa thớt. (Hóa ra 12 MB của tôi quá thấp; tất nhiên bạn cần1010b1,15GB.)
Raphael
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.