2013-05-25 16 views
12

Ví dụ, nếu các số là:Làm thế nào để sắp xếp lại một mảng theo cách như vậy mà mỗi phần tử lớn/nhỏ hơn so với các nước láng giềng

30, 12, 49, 6, 10, 50, 13 

Mảng sẽ là:

[10, 6, 30, 12, 49, 13, 50] 

Như bạn có thể thấy:

  • 6 là nhỏ hơn so với cả 10 và 30 và
  • 49 là rất tốt er hơn 12 và 13 và cứ tiếp tục như vậy.

Các con số đều khác nhau và thực tế. Tôi cần thuật toán hiệu quả nhất.

+5

Bạn cần tất cả các giải pháp hoặc chỉ là giải pháp đầu tiên? –

+0

Sẽ rất tuyệt nếu thuật toán có thể tạo ra tất cả các giải pháp. nhưng thuật toán phải là thuật toán hiệu quả nhất về thời gian. – Peggy

+1

Tôi cảm thấy rằng việc tính toán "tất cả các giải pháp" có thể có khuynh hướng phức tạp 'O (n!)' ... –

Trả lời

15

Điều này có thể được thực hiện trong thời gian O (n):

  1. Tìm trung bình trong thời gian O (n) (mô tả có sẵn trong Wikipedia
  2. Đặt mọi phần tử lớn hơn so với trung bình trên những nơi kỳ lạ và mọi phần tử nhỏ hơn - ngay cả những nơi

Tất nhiên, điều này giả định rằng tất cả các yếu tố này là khác biệt, nếu không đôi khi nó sẽ thất bại.

+0

đợi một phút! chúng ta không thể tìm thấy trung vị trong O (n) bằng cách lựa chọn, chúng ta chỉ có thể tìm thấy trung vị của các trung vị, mà không nhất thiết phải là trung vị. nó không phải là trong 50%, chỉ hơn 30% và ít hơn 70% chiều dài của mảng! – Peggy

+1

@Peggy: xin vui lòng, đọc toàn bộ bài viết Wikipedia, ngay cả khi chúng tôi có thể nhất quán chọn trục xoay với phần nhỏ nhất 30%, điều này là đủ để chọn nhanh là O (n) trong trường hợp xấu nhất. – maxim1000

+0

vâng, bạn nói đúng. sau khi tìm thấy trung vị trung bình, chúng ta lại có thể tìm thấy trung vị bằng cách tìm (n/2) phần tử nhỏ nhất thứ. (tìm phần tử nhỏ nhất kin iin O (n)). Lấy làm tiếc – Peggy

14

Giả sử tất cả các số đều khác nhau, cách dễ nhất có thể là sắp xếp các số sau đó xen kẽ nửa đầu tiên và thứ hai của danh sách được sắp xếp. Điều này sẽ đảm bảo mẫu cao/thấp/cao/thấp/cao/thấp/.... mà bạn cần.

Thuật toán này là O(n log n) cần đủ hiệu quả cho hầu hết các mục đích và có thể hưởng lợi từ các thường trình sắp xếp được tối ưu hóa trong thư viện chuẩn của bạn.

Nếu con số này không rõ rệt, sau đó nó có thể là không có giải pháp (ví dụ nếu các con số đều bình đẳng)

+0

Tôi nghĩ rằng đó sẽ là cách tốt nhất để làm điều đó – YouYou

+0

Tôi nghĩ câu trả lời này không hoàn toàn chính xác. Nếu các con số là 1, 2, 2, 3 bạn sẽ có 1 2 2 3 làm câu trả lời? khi bạn có thể có 2 1 3 2 –

+0

Tôi nghĩ câu trả lời này là chính xác – zenpoy

0

Tôi không quá am hiểu về sự phức tạp, nhưng đây là ý tưởng của tôi. đang

For even length lists: 

(For our odd length example, 
put 30 aside to make the list even) 

1. Split the list into chunks of 2 => [[12,49],[6,10],[50,13]] 
2. Sort each chunk     => [[12,49],[6,10],[13,50]] 
3. Reverse-sort the chunks by 
    comparing the last element of 
    one to the first element of 
    the second       => [[12,49],[13,50],[6,10]] 

For odd length lists: 
4. Place the removed first element in 
    the first appropriate position  => [30,12,49,13,50,6,10] 

Haskell:

import Data.List (sortBy) 
import Data.List.Split (chunksOf) 

rearrange :: [Int] -> [Int] 
rearrange xs 
    | even (length xs) = rearrangeEven xs 
    | null (drop 1 xs) = xs 
    | otherwise  = place (head xs) (rearrangeEven (tail xs)) 
where place x (y1:y2:ys) 
     | (x < y1 && y1 > y2) || (x > y1 && y1 < y2) = (x:y1:y2:ys) 
     | otherwise         = place' x (y1:y2:ys) 
     place' x (y1:y2:ys) 
     | (x < y1 && x < y2) || (x > y1 && x > y2) = (y1:x:y2:ys) 
     | otherwise        = y1 : (place' x (y2:ys)) 
     rearrangeEven = concat 
        . sortBy (\a b -> compare (head b) (last a)) 
        . map sort 
        . chunksOf 2 

Output:

*Main> rearrange [30,12,49,6,10,50,13] 
[30,12,49,13,50,6,10] 

*Main> rearrange [1,2,3,4] 
[3,4,1,2] 
+0

Điều này dường như không hoạt động. Ví dụ, đối với '[3,4,0,1,2]' nó trả về '[1,0,2,4,3]' không hợp lệ vì '2' lớn hơn' 0' nhưng ít hơn so với '4'. Một giải pháp hợp lệ trong trường hợp này sẽ là v.d. '[0,4,1,3,2]'. Tìm thấy bằng [khai thác thử nghiệm nhỏ này tôi đã viết bằng QuickCheck] (http://hpaste.org/88619). – hammar

+0

@hammar Đây là một cái gì đó thú vị: Tôi đã thay đổi một dòng, như thế này: 'prop_correct (Phân biệt xs) = lẻ (chiều dài xs) || hợp lệ (sắp xếp lại xs) 'và tôi nhận được điều này:' +++ OK, đã vượt qua 100 bài kiểm tra.' –

1

Một người nào đó đã đăng câu hỏi này làm bản dupe cho this nhưng giải pháp ở đó tốt hơn giải pháp được chấp nhận ở đây vì vậy tôi nghĩ tôi sẽ đăng câu hỏi ở đây.

Về cơ bản, khóa là cho mỗi ba số trong đó phải giữ số đó a <b> c bạn xem chuỗi và hoán đổi số lớn nhất vào giữa. Sau đó, bạn tăng thêm 2 để đến chuỗi tiếp theo như a <b> c và thực hiện tương tự.

Về mặt kỹ thuật, giải pháp vẫn chạy trong O (n) như giải pháp được chấp nhận, nhưng nó là một O (n) tốt hơn và nó đơn giản hơn nhiều vì trung bình algo là khó thực hiện. Hy vọng rằng bất cứ ai yêu thích vấn đề này sẽ ít nhất là xem giải pháp này, tôi có thể đăng mã nếu có ai quan tâm.

Các vấn đề liên quan