Nhận 100 số cao nhất từ ​​danh sách vô hạn


53

Một người bạn của tôi đã được hỏi câu hỏi phỏng vấn này -

"Có một dòng số liên tục đến từ một số danh sách số vô hạn mà bạn cần duy trì cơ sở hạ tầng để trả về 100 số cao nhất hàng đầu tại bất kỳ thời điểm nào. Giả sử tất cả các số chỉ là số nguyên."

Điều này rất đơn giản, bạn cần giữ một danh sách được sắp xếp theo thứ tự giảm dần và theo dõi số thấp nhất trong danh sách đó. Nếu số mới thu được lớn hơn số thấp nhất đó thì bạn phải xóa số thấp nhất đó và chèn số mới vào danh sách được sắp xếp theo yêu cầu.

Sau đó, câu hỏi đã được mở rộng -

"Bạn có thể chắc chắn rằng Lệnh chèn phải là O (1) không? Có thể không?"

Theo như tôi biết, ngay cả khi bạn thêm một số mới vào danh sách và sắp xếp lại nó bằng bất kỳ thuật toán sắp xếp nào, thì tốt nhất là O (logn) cho quicksort (tôi nghĩ). Vì vậy, bạn tôi nói rằng nó không thể. Nhưng anh ta không bị thuyết phục, anh ta yêu cầu duy trì bất kỳ cấu trúc dữ liệu nào khác hơn là một danh sách.

Tôi đã nghĩ về cây nhị phân cân bằng, nhưng ngay cả ở đó bạn sẽ không nhận được chèn với thứ tự 1. Vì vậy, câu hỏi tương tự bây giờ tôi cũng có. Muốn biết liệu có bất kỳ cấu trúc dữ liệu nào như vậy có thể chèn vào Thứ tự 1 cho vấn đề trên hay không hoàn toàn có thể.


19
Có thể đây chỉ là tôi hiểu nhầm câu hỏi, nhưng tại sao bạn cần phải giữ một danh sách được sắp xếp ? Tại sao không chỉ theo dõi số thấp nhất và nếu gặp một số cao hơn số đó, hãy xóa số thấp nhất và nhập số mới, mà không giữ danh sách được sắp xếp. Điều đó sẽ cung cấp cho bạn O (1).
EdoDodo

36
@EdoDodo - và sau hoạt động đó, làm thế nào để bạn biết con số thấp nhất mới là gì?
Damien_The_Unbeliever

19
Sắp xếp danh sách [O (100 * log (100)) = O (1)] hoặc thực hiện tìm kiếm tuyến tính qua nó với mức tối thiểu [O (100) = O (1)] để lấy số thấp nhất mới. Danh sách của bạn là một kích thước không đổi, vì vậy tất cả các hoạt động này cũng là thời gian không đổi.
Random832

6
Bạn không cần phải giữ toàn bộ danh sách được sắp xếp. Bạn không quan tâm con số cao nhất hoặc cao thứ 2 là gì. Bạn chỉ cần biết cái thấp nhất là gì. Vì vậy, sau khi bạn chèn một số mới, bạn chỉ cần duyệt qua 100 số và xem số nào thấp nhất. Đó là thời gian không đổi.
Tom Zych

27
Thứ tự tiệm cận của một hoạt động chỉ thú vị khi kích thước của vấn đề có thể phát triển mà không bị ràng buộc. Không rõ ràng từ câu hỏi của bạn mà số lượng đang tăng lên mà không bị ràng buộc; có vẻ như bạn đang hỏi thứ tự tiệm cận là gì đối với một vấn đề có kích thước giới hạn ở mức 100; đó thậm chí không phải là một câu hỏi hợp lý để hỏi; một cái gì đó phải được phát triển mà không bị ràng buộc. Nếu câu hỏi là "bạn có thể làm điều đó để giữ top n, không phải top 100, trong thời gian O (1) không?" sau đó câu hỏi là hợp lý.
Eric Lippert

Câu trả lời:


35

Giả sử k là số lượng số cao nhất bạn muốn biết (100 trong ví dụ của bạn). Sau đó, bạn có thể thêm một số mới trong O(k)đó cũng có O(1). Bởi vì O(k*g) = O(g) if k is not zero and constant.


6
O (50) là O (n), không phải O (1). Chèn vào danh sách độ dài N trong thời gian O (1) có nghĩa là thời gian không phụ thuộc vào giá trị của N. Điều đó có nghĩa là nếu 100 trở thành 10000, 50 KHÔNG phải trở thành 5000.

18
@hamstergene - nhưng trong trường hợp của câu hỏi này, là Nkích thước của danh sách được sắp xếp, hoặc số lượng các mặt hàng đã được xử lý cho đến nay? Nếu bạn xử lý 10000 mục và giữ 100 mục hàng đầu trong danh sách hoặc bạn xử lý 1000000000 mục và giữ 100 mục hàng đầu trong danh sách được sắp xếp, chi phí chèn trong danh sách đó sẽ giữ nguyên.
Damien_The_Unbeliever

6
@hamstergene: Trong trường hợp đó bạn đã hiểu sai những điều cơ bản. Trong liên kết wikipedia của bạn có một thuộc tính ("Nhân với hằng số") : O(k*g) = O(g) if k not zero and constant. => O(50*1) = O(1).
duedl0r

9
Tôi nghĩ duedl0r là đúng. Hãy giảm bớt vấn đề và nói rằng bạn chỉ cần các giá trị tối thiểu và tối đa. Đây có phải là O (n) vì mức tối thiểu và tối đa là 2 không? (n = 2). Số 2 là một phần của định nghĩa của vấn đề. Là một hằng số, vì vậy nó là ak trong O (k * gì đó) tương đương với O (một cái gì đó)
xanatos

9
@hamstergene: bạn đang nói về chức năng gì? giá trị 100 dường như không đổi đối với tôi ..
duedl0r

19

Giữ danh sách chưa được sắp xếp. Tìm hiểu xem có nên chèn số mới hay không sẽ mất nhiều thời gian hơn, nhưng việc chèn sẽ là O (1).


7
Tôi nghĩ rằng điều này sẽ mang lại cho bạn giải thưởng thông minh nếu không có gì khác. * 8 ')
Đánh dấu gian hàng

4
@Emilio, bạn đúng về mặt kỹ thuật - và tất nhiên đó là loại chính xác tốt nhất
Gareth

1
Nhưng bạn cũng có thể giữ mức thấp nhất trong số 100 số của mình, sau đó bạn cũng có thể quyết định xem bạn có cần chèn vào O (1) hay không. Sau đó, chỉ khi bạn chèn một số, bạn phải tìm kiếm số thấp nhất mới. Nhưng điều đó xảy ra hiếm hơn là quyết định chèn hay không, điều này xảy ra với mọi số mới.
Andrei Vajna II

12

Điều này thật dễ dàng. Kích thước của danh sách không đổi, do đó thời gian sắp xếp của danh sách là không đổi. Một hoạt động thực hiện trong thời gian không đổi được gọi là O (1). Do đó, sắp xếp danh sách là O (1) cho danh sách kích thước cố định.


9

Khi bạn vượt qua 100 số, chi phí tối đa bạn sẽ phải trả cho số tiếp theo là chi phí để kiểm tra xem số đó có nằm trong 100 số cao nhất không (hãy gắn nhãn là CheckTime ) cộng với chi phí để nhập số đó vào bộ đó và đẩy ra mức thấp nhất (hãy gọi là EnterTime ), đó là thời gian không đổi (ít nhất là đối với các số bị chặn) hoặc O (1) .

Worst = CheckTime + EnterTime

Tiếp theo, nếu phân phối số là ngẫu nhiên, chi phí trung bình sẽ giảm số lượng bạn có nhiều hơn. Ví dụ: cơ hội bạn sẽ phải nhập số thứ 101 vào tập tối đa là 100/101, cơ hội cho số thứ 1000 sẽ là 1/10 và cơ hội cho số thứ n sẽ là 100 / n. Do đó, phương trình của chúng tôi cho chi phí trung bình sẽ là:

Average = CheckTime + EnterTime / n

Do đó, khi n tiến đến vô cùng, chỉ có CheckTime là quan trọng:

Average = CheckTime

Nếu các số bị ràng buộc, CheckTime không đổi và do đó là thời gian O (1) .

Nếu các số không bị ràng buộc, thời gian kiểm tra sẽ tăng lên với nhiều số hơn. Về mặt lý thuyết, điều này là do nếu số nhỏ nhất trong tập tối đa đủ lớn, thời gian kiểm tra của bạn sẽ lớn hơn vì bạn sẽ phải xem xét nhiều bit hơn. Điều đó làm cho có vẻ như nó sẽ cao hơn một chút so với thời gian không đổi. Tuy nhiên, bạn cũng có thể lập luận rằng cơ hội số tiếp theo nằm trong tập cao nhất tiến đến 0 khi n tiến đến vô cùng và vì vậy cơ hội bạn sẽ cần xem xét thêm các bit cũng tiến đến 0, đó sẽ là đối số cho O (1) thời gian.

Tôi không tích cực, nhưng ruột của tôi nói rằng đó là thời gian O (log (log (n))) . Điều này là do cơ hội số tăng thấp nhất là logarit và cơ hội số bit bạn cần xem xét cho mỗi lần kiểm tra cũng là logarit. Tôi quan tâm đến những người khác đảm nhận việc này, vì tôi không thực sự chắc chắn ...


Ngoại trừ danh sách này là tùy ý, nếu đó là danh sách số lượng ngày càng tăng thì sao?
dan_waterworth

@dan_waterworth: Nếu danh sách vô hạn là ngẫu nhiên và chỉ xảy ra tăng lên (tỷ lệ cược sẽ là 1 / ∞!), Điều đó sẽ phù hợp với trường hợp xấu nhất của CheckTime + EnterTimemỗi số. Điều này chỉ có ý nghĩa nếu các số không bị ràng buộc, và do đó CheckTimeEnterTimecả hai sẽ tăng ít nhất là logarit do sự gia tăng kích thước của các số.
Briguy37

1
Những con số không ngẫu nhiên, có tùy ý. Thật vô nghĩa khi nói về tỷ lệ cược.
dan_waterworth

@dan_waterworth: Bây giờ bạn đã nói hai lần rằng các con số là tùy ý. bạn lấy cái này ở đâu vậy? Ngoài ra, tôi tin rằng bạn vẫn có thể áp dụng số liệu thống kê cho các số tùy ý bắt đầu bằng trường hợp ngẫu nhiên và cải thiện độ chính xác của chúng khi bạn biết thêm về trọng tài. Ví dụ: nếu bạn là trọng tài viên, có vẻ như sẽ có nhiều cơ hội lựa chọn số lượng ngày càng tăng hơn nếu, giả sử, tôi là trọng tài viên;)
Briguy37

7

Điều này là dễ dàng nếu bạn biết Cây nhị phân nhị phân . Các đống nhị phân hỗ trợ chèn trong thời gian trung bình không đổi, O (1). Và cung cấp cho bạn dễ dàng truy cập vào các yếu tố x đầu tiên.


Tại sao lưu trữ các yếu tố bạn không cần? (các giá trị quá thấp) Có vẻ như một thuật toán tùy chỉnh phù hợp hơn. Không nói rằng bạn không thể 'không thêm' các giá trị khi chúng không cao hơn giá trị thấp nhất.
Steven Jeuris

Tôi không biết, trực giác của tôi nói với tôi rằng một đống (một số hương vị) có thể kéo nó đi khá tốt. Không có nghĩa là anh ta sẽ phải giữ tất cả các yếu tố để làm như vậy. Tôi đã không nghiên cứu nó nhưng nó "cảm thấy đúng" (TM).
Giàn

3
Một heap có thể được sửa đổi để loại bỏ bất cứ thứ gì dưới mức mth (đối với heap nhị phân và k = 100, m sẽ là 7, vì số lượng nút = 2 ^ m-1). Điều này sẽ làm chậm nó, nhưng nó vẫn được khấu hao theo thời gian liên tục.
Plutor

3
Nếu bạn đã sử dụng heap nhị phân nhị phân (vì khi đó đỉnh là mức tối thiểu, bạn đang kiểm tra mọi lúc) và bạn tìm thấy một số mới> min, thì bạn phải xóa phần tử trên cùng trước khi bạn có thể chèn một phần tử mới . Loại bỏ phần tử trên cùng (tối thiểu) sẽ là O (logN) vì bạn phải duyệt qua mọi cấp độ của cây một lần. Vì vậy, về mặt kỹ thuật chỉ đúng là chèn trung bình O (1) vì trong thực tế, nó vẫn là O (logN) mỗi khi bạn tìm thấy một số> phút.
Scott Whitlock

1
@Plutor, bạn đang giả sử một số đảm bảo rằng các đống nhị phân không cung cấp cho bạn. Hình dung nó như một cây nhị phân, có thể là trường hợp mỗi phần tử trong nhánh bên trái nhỏ hơn bất kỳ phần tử nào trong nhánh bên phải, nhưng bạn cho rằng các phần tử nhỏ nhất nằm gần gốc nhất.
Peter Taylor

6

Nếu bằng câu hỏi mà người phỏng vấn thực sự muốn hỏi, chúng ta có thể đảm bảo rằng mỗi số đến được xử lý theo thời gian không đổi, thì như nhiều người đã chỉ ra (ví dụ: xem câu trả lời của @ duedl0r), giải pháp của bạn của bạn đã là O (1) và nó sẽ là như vậy ngay cả khi anh ta đã sử dụng danh sách chưa sắp xếp, hoặc sử dụng sắp xếp bong bóng, hoặc bất cứ điều gì khác. Trong trường hợp này, câu hỏi không có nhiều ý nghĩa, trừ khi đó là câu hỏi khó hoặc bạn nhớ sai.

Tôi cho rằng câu hỏi của người phỏng vấn là có ý nghĩa, rằng anh ta không hỏi làm thế nào để biến một cái gì đó thành O (1) mà rõ ràng là như vậy.

Bởi vì độ phức tạp của thuật toán đặt câu hỏi chỉ có ý nghĩa khi kích thước của đầu vào tăng vô hạn và đầu vào duy nhất có thể phát triển ở đây là 100 kích thước danh sách; Tôi cho rằng câu hỏi thực sự là chúng tôi có thể đảm bảo rằng chúng tôi nhận được Top N dành O (1) thời gian cho mỗi số (không phải O (N) như trong giải pháp của bạn bè bạn không?

Điều đầu tiên bạn nghĩ đến là tính sắp xếp, sẽ mua độ phức tạp của thời gian O (1) cho mỗi số cho bài toán Top-N cho giá sử dụng không gian O (m), trong đó m là độ dài của phạm vi số đến . Vì vậy, có, nó là có thể.


4

Sử dụng hàng đợi ưu tiên tối thiểu được triển khai với một đống Fibonacci , có thời gian chèn không đổi:

1. Insert first 100 elements into PQ
2. loop forever
       n = getNextNumber();
       if n > PQ.findMin() then
           PQ.deleteMin()
           PQ.insert(n)

4
"Hoạt động xóa và xóa công việc tối thiểu trong O(log n)thời gian khấu hao" , vì vậy đây vẫn sẽ dẫn đến O(log k)nơi klà số tiền các hạng mục để lưu trữ.
Steven Jeuris

1
Điều này không khác gì câu trả lời của Emilio , được mệnh danh là "giải thưởng thông minh" vì min min hoạt động trong O (log n) (theo Wikipedia).
Nicole

@Renesis Câu trả lời của Emilio sẽ là O (k) để tìm mức tối thiểu, của tôi là O (log k)
Gabe Moothart

1
@Gabe Đủ rồi, tôi chỉ có ý nghĩa về nguyên tắc. Nói cách khác, nếu bạn không lấy 100 là hằng số, thì câu trả lời này cũng không phải là thời gian.
Nicole

@Renesis Tôi đã xóa câu lệnh (không chính xác) khỏi câu trả lời.
Gabe Moothart

2

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:

  1. 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.

  2. Lấy một số mới x từ luồng ngẫu nhiên.

  3. 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

  4. 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)

  5. 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)

  6. 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).

  7. 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)

  8. 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.


1
Tìm kiếm phải là một phần của chức năng chèn - chúng không phải là các chức năng độc lập. Vì tìm kiếm của bạn là O (n), nên hàm chèn của bạn cũng là O (n).
Kirk Broadhurst

Không. Sử dụng chiến lược tôi đã mô tả, trong đó nhiều hashtables được sử dụng để vượt qua không gian số nhanh hơn, đó là O (1). Xin vui lòng đọc câu trả lời của tôi một lần nữa.
Benedict

1
@Benedict, câu trả lời của bạn nói khá rõ ràng rằng nó có các tìm kiếm tuyến tính trong bước 4 và 7. Tìm kiếm tuyến tính không phải là O (1).
Peter Taylor

Vâng, nó có, nhưng tôi đối phó với điều đó sau. Bạn có phiền thực sự đọc phần còn lại xin vui lòng. Nếu cần tôi sẽ chỉnh sửa câu trả lời của mình để làm cho nó thật rõ ràng.
Benedict

@Benedict Bạn đúng - không bao gồm tìm kiếm, câu trả lời của bạn là O (1). Thật không may, giải pháp này sẽ không hoạt động mà không tìm kiếm.
Kirk Broadhurst

1

Chúng ta có thể giả sử rằng các số có kiểu dữ liệu cố định, chẳng hạn như Integer không? Nếu vậy, sau đó giữ một kiểm đếm của mỗi số được thêm vào. Đây là một hoạt động O (1).

  1. Khai báo một mảng có càng nhiều phần tử càng tốt:
  2. Đọc từng số khi nó được truyền phát.
  3. Kiểm đếm số lượng. Bỏ qua nó nếu con số đó đã được tính 100 lần vì bạn sẽ không bao giờ cần đến nó. Điều này ngăn chặn tràn ra kiểm đếm nó vô số lần.
  4. Lặp lại từ bước 2.

Mã VB.Net:

Const Capacity As Integer = 100

Dim Tally(Integer.MaxValue) As Integer ' Assume all elements = 0
Do
    Value = ReadValue()
    If Tally(Value) < Capacity Then Tally(Value) += 1
Loop

Khi bạn trả lại danh sách, bạn có thể mất bao lâu tùy thích. Chỉ cần lặp lại từ cuối danh sách và tạo một danh sách mới gồm 100 giá trị cao nhất được ghi lại. Đây là một hoạt động O (n), nhưng điều đó không liên quan.

Dim List(Capacity) As Integer
Dim ListCount As Integer = 0
Dim Value As Integer = Tally.Length - 1
Dim ValueCount As Integer = 0
Do Until ListCount = List.Length OrElse Value < 0
    If Tally(Value) > ValueCount Then
        List(ListCount) = Value
        ValueCount += 1
        ListCount += 1
    Else
        Value -= 1
        ValueCount = 0
    End If
Loop
Return List

Chỉnh sửa: Trên thực tế, nó không thực sự quan trọng nếu đó là loại dữ liệu cố định. Do không có giới hạn áp đặt đối với mức tiêu thụ bộ nhớ (hoặc đĩa cứng), bạn có thể thực hiện công việc này cho bất kỳ phạm vi số nguyên dương nào.


1

Một trăm số được lưu trữ dễ dàng trong một mảng, kích thước 100. Bất kỳ cây, danh sách hoặc tập hợp nào đều quá mức, được giao nhiệm vụ trong tay.

Nếu số đến cao hơn mức thấp nhất (= cuối cùng) trong mảng, hãy chạy qua tất cả các mục. Khi bạn tìm thấy số đầu tiên nhỏ hơn số mới của mình (bạn có thể sử dụng các tìm kiếm ưa thích để làm điều đó), hãy chạy qua phần còn lại của mảng, đẩy từng mục "xuống" một.

Vì bạn giữ danh sách được sắp xếp từ đầu, bạn không cần phải chạy bất kỳ thuật toán sắp xếp nào cả. Đây là O (1).


0

Bạn có thể sử dụng Binary Max-Heap. Bạn sẽ phải theo dõi một con trỏ đến nút tối thiểu (có thể không xác định / null).

Bạn bắt đầu bằng cách chèn 100 số đầu tiên vào heap. Tối đa sẽ ở trên cùng. Sau khi hoàn thành, bạn sẽ luôn giữ 100 số trong đó.

Sau đó, khi bạn nhận được một số mới:

if(minimumNode == null)
{
    minimumNode = findMinimumNode();
}
if(newNumber > minimumNode.Value)
{
    heap.Remove(minimumNode);
    minimumNode = null;
    heap.Insert(newNumber);
}

Thật không may findMinimumNodelà O (n) và bạn phải chịu chi phí đó một lần cho mỗi lần chèn (nhưng không phải trong quá trình chèn :). Trung bình loại bỏ nút tối thiểu và chèn nút mới, trung bình là O (1) vì chúng sẽ có xu hướng về phía dưới của heap.

Đi theo một cách khác với Heap Mininary Heap, min ở trên cùng, rất phù hợp để tìm min để so sánh, nhưng thật tệ khi bạn phải thay thế tối thiểu bằng một số mới> min. Đó là bởi vì bạn phải loại bỏ nút min (luôn là O (logN)) và sau đó chèn nút mới (trung bình O (1)). Vì vậy, bạn vẫn có O (logN) tốt hơn Max-Heap, nhưng không có O (1).

Tất nhiên, nếu N không đổi, thì bạn luôn có O (1). :)

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.