tìm các phần tử k nhỏ nhất trong mảng trong O (k)


12

Đây là một câu hỏi thú vị tôi đã tìm thấy trên web. Cho một mảng chứa n số (không có thông tin về chúng), chúng ta nên xử lý trước mảng theo thời gian tuyến tính để có thể trả về k phần tử nhỏ nhất trong thời gian O (k), khi chúng ta được cấp số 1 <= k <= n

Tôi đã thảo luận vấn đề này với một số người bạn nhưng không ai có thể tìm ra giải pháp; Bất kỳ trợ giúp sẽ được đánh giá cao!

ghi chú nhanh: - thứ tự của các phần tử k nhỏ nhất không quan trọng - các phần tử trong mảng là số, có thể là số nguyên và có thể không (vì vậy không có sắp xếp cơ số) - số k không biết trong giai đoạn tiền xử lý. tiền xử lý là thời gian O (n). hàm (tìm k phần tử nhỏ nhất) trên thời gian O (k).


4
Làm thế nào về việc sử dụng một đống nhỏ?
Shir

1
Nhìn vào tính toán k-skyband và top-k. Bài viết cs.sfu.ca/~jpei/publications/subsky_tkde07.pdf có một đánh giá tốt về các tài liệu liên quan.
András Salamon

1
Shir-Tôi đã xem xét ý tưởng đống nhỏ. tuy nhiên, để in k số nhỏ nhất trong heap tối thiểu là trong thời gian O (klogn) và không phải O (k) như yêu cầu
Idan

4
@idannik: Tại sao bạn nghĩ phải mất thời gian để tìm k yếu tố nhỏ nhất trong một min-heap? Ω(klogn)k
Kristoffer Arnsfelt Hansen

8
Tôi không nghĩ đây là cấp độ nghiên cứu. Nó trông giống như một nhiệm vụ. Bạn đã tìm nó ở đâu?
Kaveh

Câu trả lời:


24

Tiền xử lý mảng giá trị trong thời gian O ( n ) :nO(n)

  • in
  • trong khi i>2
    • Tính trung vị của A [ 1 .. i ] trong thời gian O ( i )mA[1..i]O(i)
    • phân vùng vào A [ 1 .. i / 2 - 1 ] mA [ i / 2 + 1 .. i ] m trong cùng một lúc.A[1..i]A[1..i/21]mA[i/2+1..i]m
    • ii/2

Tổng thời gian tính toán trước là trong O(1+2+4+...+n)O(n)

Trả lời truy vấn cho phần tử nhỏ nhất trong A trong thời gian O ( k ) :kAO(k)

  • llog2k
  • chọn thứ nguyên tố x của A [ 2 l . 0,2 l + 1 ] trong thời gian O ( 2 l ) O ( k )(k2l)xA[2l..2l+1]O(2l)O(k)
  • phân vùng bởi x cùng một lúcA[2l..2l+1]x

chứa k phần tử nhỏ nhất.A[1..k]k

Người giới thiệu:

  • Năm 1999, Dor và Zwick đã đưa ra một thuật toán để tính trung bình của phần tử theo thời gian trong các phép so sánh 2.942 n + o ( n ) , đưa ra thuật toán để chọn phần tử thứ k từ n phần tử không có thứ tự trong ít hơn 6 n so sánh.n2.942n+o(n)kn6n

1
Tôi đoán các vòng ngoài được coi là 'for i in '. Thuật toán của bạn có khác với câu trả lời của Yuval Filmus không? {2lgn,,4,2,1}
Radu GRIGore

2
Đây là một khái quát của thuật toán của tôi để tùy ý . Nó cũng đánh vần một số chi tiết thực hiện (cố tình) bỏ qua câu trả lời của tôi. n
Yuval Filmus

3
@YuvalFilmus Bạn có muốn ám chỉ bởi nhận xét của bạn rằng câu trả lời của tôi gần với bạn không? Đây là giải pháp mà tôi nghĩ đến khi tôi xem xét câu hỏi. Tôi thấy rằng bạn đã đăng một cái tương tự, nhưng thấy nó không rõ ràng, vì vậy tôi đã viết riêng của tôi (trái ngược với việc thực hiện một chỉnh sửa lớn của bạn). Điều quan trọng cuối cùng là chất lượng của các câu trả lời trên các hệ thống, chứ không thực sự ai đã viết chúng: các huy hiệu và danh tiếng chỉ là sự khuyến khích, không phải là mục tiêu trong chính chúng.
Jeremy

4
@Jeremy Không hề; Chỉ là hai giải pháp là như nhau (nhưng giải pháp của bạn hoạt động cho n tùy ýn ) và tôi không đưa ra chi tiết trong trường hợp đó thực sự là một câu hỏi bài tập về nhà.
Yuval Filmus

2
Oh :( Xin lỗi về điều đó sau đó. (Mặc dù tôi vẫn nghĩ rằng việc đưa ra câu trả lời đầy đủ là ưu tiên hơn những nghi ngờ chuyển nhượng)
Jeremy

14

Giả sử cho đơn giản rằng . Sử dụng thuật toán chọn thời gian tuyến tính để tìm các phần tử tại các vị trí 2 m - 1 , 2 m - 2 , 2 m - 3 , Hoài , 1 ; điều này cần thời gian tuyến tính. Với k , tìm t2 t - 1k 2 t ; lưu ý rằng 2 t2 k . Lọc ra tất cả các yếu tố xếp hạng tối đa 2 tn=2m2m1,2m2,2m3,,1kt2t1k2t2t2k2t và hiện sử dụng thuật toán chọn thời gian tuyến tính để tìm phần tử tại vị trí trong thời giank .O(2t)=O(k)

Làm rõ: Nó có vẻ rằng tiền xử lý mất nhiều thời gian , và đó thực sự là trường hợp nếu bạn không cẩn thận. Đây là cách thực hiện tiền xử lý trong thời gian tuyến tính:Θ(nlogn)

while n > 0:
  find the (lower) median m of A[0..n-1]
  partition A in-place so that A[n/2-1] = m
  n = n/2

Phân vùng tại chỗ được thực hiện như trong quicksort. Thời gian chạy là tuyến tính trong , và do đó tuyến tính. Cuối cùng, mảng A thỏa mãn tính chất sau: với mỗi k , A [ 0 .. n / 2 k - 1 ] bao gồm các phần tử nhỏ nhất n / 2 k .n+n/2+n/4++1<2nAkA[0..n/2k1]n/2k


1
Một cách tự nhiên. Nếu mảng được sắp xếp mà bạn có thể giải quyết điều này trong mà không cần tiền xử lý. Có lẽ bạn không biết về thuật toán chọn thời gian tuyến tính có thể tìm thấy phần tử lớn thứ k trong thời gian O ( n ) ? O(1)kO(n)
Yuval Filmus

4
@Yuval Filmus: Bạn không chạy thuật toán lần, với tổng số n log n bước? Hay bạn đã có một số loại xen kẽ trong tâm trí? lognnlogn
András Salamon

3
@ AndrásSalamon: Nếu bạn đọc câu trả lời được đưa ra bởi Jeremy (trông giống như câu này), bạn sẽ thấy rằng trước tiên bạn xử lý toàn bộ mảng, sau đó là nửa đầu, v.v.
Radu GRIGore

3
@ AndrásSalamon Radu là chính xác. Sau khi bạn tìm thấy trung vị, bạn phân vùng mảng (tại chỗ) thành nửa dưới và trên của nó, sau đó lặp lại ở nửa dưới. Thời gian chạy sau đó tỷ lệ thuận với . n+n/2+n/4++1<2n
Yuval Filmus

5
Ngẫu nhiên thuật toán này xuất hiện dưới dạng chương trình con trong câu trả lời của tôi cho một câu hỏi trước đó: cstheory.stackexchange.com/questions/17378/ phỏng
David Eppstein

2

Đầu tiên sử dụng O(n) để xây dựng một đống nhỏ. Được biết, chúng ta có thể sử dụng O(k) để tìmk

Frederickson, Greg N. , Một thuật toán tối ưu để lựa chọn trong một heap , Inf. Tính toán. 104, số 2, 197-214 (1993).ZBL0818.68065 ..


1
Tôi không thấy làm thế nào chúng ta có thể trích xuất các phần tử nhỏ nhất từ một heap trong thời gian O ( k ) , vì việc loại bỏ từng phần tử mất thời gian logarit theo kích thước của heap. Bạn có thể làm rõ những gì bạn đã nghĩ trong đây? Cảm ơn! kO(k)
a3nm

@ a3nm Đây thực sự không phải là một thuật toán đơn giản, nhưng tôi đã cập nhật tài liệu tham khảo.
hqztrue

kkO(k)k

k-th smallest element x. However after knowing that, you can just perform a dfs in the heap to find all elements <x in O(k).
hqztrue

Sorry I don't see which DFS you would perform to find these elements? (Some of them may not be ancestors of the k-th smallest element in the heap, i.e., as far as I can tell locating, e.g., the k/2-th element knowing the position of the k-th element is not trivial.)
a3nm

0

Use linear time selection to find the kth largest element, then do a partition step from quicksort using the kth largest element as the pivot.


1
The original question mentions that k is not known at preprocessing time....
Jeremy

2
I see. My mistake.
jbapple
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.