2012-02-26 6 views

Trả lời

3

Khi @orangeoctopus, sử dụng thuật toán xếp hạng chuẩn trên bộ sưu tập của n chuỗi có kích thước n sẽ dẫn đến tính toán O(n^2 * logn).

Tuy nhiên - lưu ý rằng bạn có thể làm điều đó trong O(n^2), với các biến thể trên radix sort.

Cách đơn giản nhất để làm điều đó [theo ý kiến ​​của tôi] - là

  1. xây dựng một trie, và cư nó với tất cả các chuỗi của bạn. Nhập mỗi chuỗi là O(n) và bạn làm điều đó n lần - tổng số O(n^2)
  2. làm DFS trên trie, mỗi lần bạn gặp dấu chấm hết cho chuỗi - thêm nó vào bộ sưu tập được sắp xếp. Thứ tự của các chuỗi được thêm vào theo cách này là từ điển, do đó danh sách của bạn sẽ được sắp xếp theo từ điển khi bạn hoàn thành.

Nó rất dễ dàng để xem bạn không thể làm điều đó tốt hơn bất kỳ sau đó O(n^2), vì chỉ đọc dữ liệu là O(n^2), do đó giải pháp này là tối ưu về mặt ký hiệu O lớn thời gian phức tạp.

+0

Tôi nghĩ thay vì nói "DFS", hãy nói "truyền tải trật tự trước" sẽ rõ ràng hơn. – CEGRD

+0

Có thể 'O (n^2)' đạt được mà không cần sử dụng trie? – Kshitij

+0

@Kshitij Vâng, thực hiện một kiểu radix trên chuỗi, trie chỉ là một gợi ý - một loại radix tiêu chuẩn sẽ hoạt động ở đây - sử dụng các ký tự (hoặc bit đại diện của chúng) mỗi lần lặp để đạt được thứ tự một phần hiện tại, cho đến khi bạn xả hết bit /nhân vật. Điều này cũng sẽ có 'O (n^2)'. – amit

6

Khi bạn đang nói về O ký hiệu với hai thứ có độ dài khác nhau, thông thường bạn muốn sử dụng các biến khác nhau, như MN.

Vì vậy, nếu loại hợp nhất của bạn là O(N log N), nơi N là số chuỗi ... và so sánh hai chuỗi là O(M) nơi M quy mô với chiều dài của chuỗi, sau đó bạn sẽ được trái với:

O(N log N) * O(M) 

hoặc

O(M N log N) 

nơi M là chiều dài chuỗi và N là số chuỗi. Bạn muốn sử dụng các nhãn khác nhau vì chúng không có nghĩa giống nhau.

Trong trường hợp kỳ lạ nơi chiều dài chuỗi trung bình tỉ lệ với số chuỗi, như thế nào nếu bạn đã có một ma trận lưu trữ trong chuỗi hoặc một cái gì đó như thế, bạn có thể tranh luận rằng M = N, và sau đó bạn sẽ phải O(N^2 log N)

+0

Bạn không có nghĩa là "O (M) trong đó M ..." thay vì "O (N) trong đó N ..."? Và trong khi đó là hiệu suất trường hợp xấu nhất, theo yêu cầu, cần lưu ý rằng hiệu suất trung bình của trường hợp để so sánh hai chuỗi là O (1) vì nó trở nên ít hình học hơn và ít có khả năng bạn sẽ cần phải truy cập từng ký tự bổ sung trong chuỗi. – xan

+0

Chắc chắn, tôi có nghĩa là họ tách biệt nhưng tôi đã thay đổi nó để sử dụng 'M' để rõ ràng hơn. Anh ấy yêu cầu "sự phức tạp tồi tệ nhất", nhưng cho một kích thước "trung bình" sting ... vì vậy nó vẫn còn O (N), phải không? –

+0

Có, câu hỏi là một chút không rõ ràng với sự pha trộn của nó tồi tệ nhất và trung bình. Tôi nghĩ câu trả lời của bạn sẽ mạnh mẽ hơn để trang trải cả hai. – xan

0

Sắp xếp mục n với MergeSort yêu cầu số O(N LogN) so sánh. Nếu thời gian so sánh hai mục là O(1) thì tổng thời gian chạy sẽ là O(N logN). Tuy nhiên, so sánh hai chuỗi độ dài N yêu cầu O(N) thời gian, do đó, việc triển khai ngây thơ có thể bị kẹt với thời gian O(N*N logN).

Điều này có vẻ lãng phí vì chúng tôi không tận dụng lợi thế của thực tế là chỉ có N chuỗi xung quanh để so sánh. Chúng ta bằng cách nào đó có thể xử lý trước các chuỗi để so sánh mất ít thời gian hơn trung bình.

Đây là một ý tưởng. Tạo một cấu trúc Trie và đặt N chuỗi ở đó. Trie sẽ có O(N*N) nút và yêu cầu O(N*N) thời gian để xây dựng. Traverse cây và đặt một số nguyên "xếp hạng" cho mỗi nút tại cây; Nếu R (N1) < R (N2) thì chuỗi liên kết với Node1 xuất hiện trước chuỗi được liên kết với Node2 trong từ điển.

Bây giờ, hãy tiếp tục với Mergesort, thực hiện so sánh trong O(1) thời gian bằng cách tra cứu Trie. Tổng thời gian chạy sẽ là O(N*N + N*logN) = O(N*N)

Chỉnh sửa: Câu trả lời của tôi rất giống với @amit. Tuy nhiên tôi tiến hành với mergesort, nơi ông tiến hành với radixsort sau khi bước xây dựng trie.

+0

Bạn cũng có giữ một từ ánh xạ chỉ mục đến các nút trie để bạn có thể truy cập các thứ hạng đó trong khi sắp xếp hợp nhất không? làm rõ xin vui lòng. Ngoài ra, tôi nghĩ bạn cũng nên bao gồm chi phí đi qua. Vì vậy, độ phức tạp nên là O (N * N + N * N + N * logN). Nếu điều này là đúng, thì phương pháp sắp xếp radix có vẻ tốt hơn vì nó là O (N * N + N * N). – CEGRD

+0

@CERGD: Ký hiệu Big O chỉ dựa trên sự tăng trưởng tiệm cận về kích thước đầu vào; nó không đối phó với các yếu tố không đổi, O (2 * N * N + NlogN) = O (N * N). Xem xét lại câu hỏi sau một vài tháng, rõ ràng là câu trả lời của amit đơn giản và nhanh hơn. Tuy nhiên, tôi không đồng ý với lập luận của bạn: cách duy nhất để đo lường hiệu suất thực tế là sử dụng một chronometer, không phải để xem xét các yếu tố liên tục trong O-ký hiệu. Thậm chí có trường hợp thuật toán với hàm O() lớn hơn đánh bại hàm kia trong các tình huống thực tế. –