Nhiệm vụ rõ ràng là tìm một thuật toán có O (1) theo độ dài N của danh sách các số cần thiết. Vì vậy, không có vấn đề gì nếu bạn cần 100 số hàng đầu hoặc 10000 số, thời gian chèn phải là O (1).
Mẹo ở đây là mặc dù yêu cầu O (1) được đề cập cho phần chèn danh sách, câu hỏi không nói gì về thứ tự thời gian tìm kiếm trong toàn bộ không gian số, nhưng hóa ra điều này có thể được thực hiện O (1) cũng. Giải pháp sau đó là như sau:
Sắp xếp một hashtable với các số cho các khóa và các cặp con trỏ danh sách được liên kết cho các giá trị. Mỗi cặp con trỏ là điểm bắt đầu và kết thúc của chuỗi danh sách được liên kết. Điều này thường sẽ chỉ là một yếu tố sau đó tiếp theo. Mỗi phần tử trong danh sách được liên kết đi bên cạnh phần tử có số cao nhất tiếp theo. Do đó, danh sách được liên kết chứa chuỗi các số được yêu cầu sắp xếp. Giữ một bản ghi của số thấp nhất.
Lấy một số mới x từ luồng ngẫu nhiên.
Có cao hơn con số thấp nhất được ghi nhận cuối cùng không? Có => Bước 4, Không => Bước 2
Nhấn bảng băm với số vừa lấy. Có một mục? Có => Bước 5. Không => Lấy số mới x-1 và lặp lại bước này (đây là một tìm kiếm tuyến tính đi xuống đơn giản, chỉ cần chịu đựng ở đây, điều này có thể được cải thiện và tôi sẽ giải thích làm thế nào)
Với phần tử danh sách vừa thu được từ bảng băm, hãy chèn số mới ngay sau phần tử trong danh sách được liên kết (và cập nhật hàm băm)
Lấy số l thấp nhất được ghi lại (và xóa nó khỏi hàm băm / danh sách).
Nhấn bảng băm với số vừa lấy. Có một mục? Có => Bước 8. Không => Lấy số mới l + 1 và lặp lại bước này (đây là một tìm kiếm tuyến tính đi lên đơn giản)
Với một hit tích cực, số trở thành số thấp nhất mới. Chuyển đến bước 2
Để cho phép các giá trị trùng lặp, hàm băm thực sự cần duy trì bắt đầu và kết thúc chuỗi danh sách được liên kết của các phần tử được sao chép. Thêm hoặc xóa một phần tử tại một khóa đã cho, do đó làm tăng hoặc giảm phạm vi được trỏ đến.
Chèn ở đây là O (1). Các tìm kiếm được đề cập là, tôi đoán một cái gì đó như, O (chênh lệch trung bình giữa các số). Sự khác biệt trung bình tăng theo kích thước của không gian số, nhưng giảm theo độ dài cần thiết của danh sách các số.
Vì vậy, chiến lược tìm kiếm tuyến tính khá kém, nếu không gian số lớn (ví dụ: đối với loại int 4 byte, 0 đến 2 ^ 32-1) và N = 100. Để giải quyết vấn đề về hiệu suất này, bạn có thể giữ các bộ hashtables song song, trong đó các số được làm tròn đến cường độ cao hơn (ví dụ 1, 10, 100, 1000) để tạo các khóa phù hợp. Bằng cách này, bạn có thể bước lên và xuống bánh răng để thực hiện các tìm kiếm cần thiết nhanh hơn. Hiệu suất sau đó trở thành một O (log numberrange), tôi nghĩ, không đổi, tức là O (1) cũng vậy.
Để làm cho điều này rõ ràng hơn, hãy tưởng tượng rằng bạn có số 197 trong tay. Bạn nhấn bảng băm 10 giây, với '190', nó được làm tròn đến mười điểm gần nhất. Có gì không Không. Vì vậy, bạn đi xuống sau 10 giây cho đến khi bạn nhấn 120. Sau đó, bạn có thể bắt đầu ở 129 trong hashtable 1s, sau đó thử 128, 127 cho đến khi bạn đạt được điều gì đó. Bây giờ bạn đã tìm thấy vị trí trong danh sách được liên kết để chèn số 197. Trong khi đưa nó vào, bạn cũng phải cập nhật hashtable 1s với mục 197, hashtable 10s với số 190, 100 với 100, v.v. bạn phải làm ở đây gấp 10 lần nhật ký của dãy số.
Tôi có thể đã có một số chi tiết sai, nhưng vì đây là trao đổi của các lập trình viên, và bối cảnh là các cuộc phỏng vấn, tôi hy vọng những điều trên là một câu trả lời đủ thuyết phục cho tình huống đó.
EDIT Tôi đã thêm một số chi tiết bổ sung ở đây để giải thích sơ đồ băm song song và ý nghĩa của các tìm kiếm tuyến tính kém mà tôi đã đề cập có thể được thay thế bằng tìm kiếm O (1). Tất nhiên tôi cũng nhận ra rằng không cần phải tìm kiếm số thấp nhất tiếp theo, bởi vì bạn có thể bước thẳng tới nó bằng cách tìm trong hàm băm với số thấp nhất và chuyển sang phần tử tiếp theo.